ChatGPT解决这个技术问题 Extra ChatGPT

UTF-8 可以编码多少个字符?

如果 UTF-8 是 8 位,是不是意味着最多只能有 256 个不同的字符?

前 128 个代码点与 ASCII 中的相同。但它说UTF-8可以支持多达百万个字符?

这是如何运作的?

在 Unicode 的 UTF-8、UTF-16、UTF-32 编码中,数字是其代码单元中的位数,其中一个或多个编码一个 Unicode 代码点。

m
mklement0

UTF-8 并不总是使用一个字节,它是 1 到 4 个字节。

前 128 个字符(US-ASCII)需要一个字节。接下来的 1,920 个字符需要两个字节来编码。这涵盖了几乎所有拉丁字母的其余部分,以及希腊语、西里尔语、科普特语、亚美尼亚语、希伯来语、阿拉伯语、叙利亚语和塔纳字母,以及组合变音符号。其余基本多语言平面中的字符需要三个字节,其中包含几乎所有常用字符[12],包括大多数中文、日文和韩文 [CJK] 字符。 Unicode 其他平面中的字符需要四个字节,其中包括不太常见的 CJK 字符、各种历史文字、数学符号和表情符号(象形符号)。

来源:Wikipedia


嗨@zwippie 我是新手。有些东西我不明白。! BMP使用2个字节你说是3个?我错了吗?
@chiperortiz,BMP 确实是 16 位,因此可以将其编码为 UTF-16,每个字符的长度恒定(UTF-16 也支持超过 16 位,但这是一种困难的做法,许多实现不支持它)。但是,对于 UTF-8,您还需要对其长度进行编码,因此会丢失一些位。这就是为什么您需要 3 个字节来编码完整的 BMP。这可能看起来很浪费,但请记住 UTF-16 始终使用 2 个字节,但 UTF-8 对大多数基于拉丁语的语言字符使用每个字符一个字节。使其紧凑两倍。
OP 问题的主旨与为什么它被称为 UTF-8 有关——这并没有真正回答这个问题。
@sanderd17 utf8 和 16 之间的区别在于 utf-8 可以使用至少 1 个字节(对于拉丁语来说足够),而 16 至少需要 2 个字节?
C
CodeClown42

UTF-8 每个字符使用 1-4 个字节:一个字节用于 ascii 字符(前 128 个 unicode 值与 ascii 相同)。但这只需要 7 位。如果设置了最高(“符号”)位,则表示多字节序列的开始;设置的连续高位的数量表示字节数,然后是 0,其余位对值有贡献。对于其他字节,最高两位是 1 和 0,其余 6 位是值。

因此,一个四字节序列将从 11110... 开始(并且 ... = 三个位的值),然后三个字节,每个 6 位的值,产生一个 21 位的值。 2^21 超过了 unicode 字符的个数,所以所有的 unicode 都可以用 UTF8 表示。


@尼克L。不,我的意思是 3 个字节。在该示例中,如果多字节序列的第一个字节从 1111 开始,则第一个 1 表示它是多字节序列的开始,那么其后连续 1 的数量表示序列中附加字节的数量(所以第一个字节将从 110、1110 或 11110 开始)。
在 RFC 3629 中找到了您的话的证据。tools.ietf.org/html/rfc3629#section-3。但是,我不明白为什么我需要在第二个字节 110xxxxxx 10xxxxxx 的开头放置“10”?为什么不只是 110xxxxx xxxxxxxx ?
softwareengineering.stackexchange.com/questions/262227/… 中找到答案。仅出于安全原因(以防流中间的单个字节损坏)
@kolobok 啊。在不安全的情况下,您可以将 21 位值编码为 3 个字节(3 位表示长度,加上 21 位)。 :D 可能这不是那么有意义,至少 WRT 西方语言。
@NickL“所以一个四字节序列将以 11110 开头......(...... = 三个字节的值)”应该读为“...... = 三个位”(谢谢)。这就是为什么 4 字节 utf8 字符具有 21 位值 (3 + 6 + 6 + 6) 的原因。
i
ijmacd

Unicode 与 UTF-8

Unicode 将代码点解析为字符。 UTF-8 是 Unicode 的一种存储机制。 Unicode 有一个规范。 UTF-8 有一个规范。他们都有不同的限制。 UTF-8 有不同的上界。

统一码

Unicode 用 "planes." 指定每个平面带有 216 个代码点。 Unicode 中有 17 个平面。总共 17 * 2^16 个代码点。 first plane, plane 0 or the BMP 的特殊之处在于它承载的重量。

与其解释所有的细微差别,我只引用上面关于飞机的文章。

17 个平面可容纳 1,114,112 个代码点。其中,2,048 个是代理,66 个是非字符,137,468 个保留供私人使用,剩下 974,530 个用于公共分配。

UTF-8

现在让我们回到上面链接的文章,

UTF-8 使用的编码方案被设计为具有更大的 231 个代码点(32,768 个平面)的限制,即使限制为 4 个字节,也可以编码 221 个代码点(32 个平面)。 [3]由于 Unicode 将码点限制为 UTF-16 可以编码的 17 个平面,因此 0x10FFFF 以上的码点在 UTF-8 和 UTF-32 中无效。

所以你可以看到你可以把不是有效 Unicode 的东西放入 UTF-8 中。为什么?因为 UTF-8 可以容纳 Unicode 甚至不支持的代码点。

UTF-8,即使有四个字节的限制,也支持 221 个码位,远远超过 17 * 2^16


C
Community

根据 this table* UTF-8 应该支持:

231 = 2,147,483,648 个字符

但是,RFC 3629 限制了可能的值,所以现在我们是 capped at 4 bytes,这给了我们

221 = 2,097,152 个字符

请注意,这些字符中有很大一部分是“保留”用于自定义使用的,这对于图标字体来说实际上非常方便。

* 维基百科使用了一个 6 字节的表格——他们已经更新了这篇文章。

2017-07-11:更正了重复计算用多个字节编码的相同代码点


这个答案是重复计算可能的编码数量。一旦你计算了所有的 2^7,你就不能在 2^11、2^16 等中再次计算它们。可能的正确编码数量是 2^21(尽管当前并非全部都在使用)。
@Jimmy你确定我在重复计算吗? 0xxxxxxx 提供 7 个可用位,110xxxxx 10xxxxxx 提供 11 个以上 - 没有重叠。第一个字节在第一种情况下以 0 开头,在第二种情况下以 1 开头。
@mpen 那么 00000001 存储什么代码点以及 11000000 100000001 存储什么?
@EvanCarroll 呃....点了。没有意识到有多种方法可以编码相同的代码点。
M
Manu Manjunath

UTF-8 可以潜在地编码 2,164,864 个“字符”。

这个数字是 27 + 211 + 216 + 221,它来自编码的工作方式:

1 字节字符有 7 位用于编码 0xxxxxxx (0x00-0x7F)

2 字节字符有 11 位用于编码 110xxxxxx 10xxxxxx(第一个字节为 0xC0-0xDF;第二个字节为 0x80-0xBF)

3 字节字符有 16 位用于编码 1110xxxx 10xxxxxx 10xxxxxx(第一个字节为 0xE0-0xEF;连续字节为 0x80-0xBF)

4 字节字符有 21 位用于编码 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx(第一个字节为 0xF0-0xF7;连续字节为 0x80-0xBF)

如您所见,这比当前的 Unicode(1,112,064 个字符)大得多。

更新

我最初的计算是错误的,因为它没有考虑额外的规则。有关更多详细信息,请参阅对此答案的评论。


您的数学不尊重 UTF-8 规则,即只允许最短的代码单元序列对代码点进行编码。因此,00000001 对 U+0001 有效,但 11110000 10000000 10000000 10000001 无效。参考:Table 3-7. Well-Formed UTF-8 Byte Sequences。此外,表格直接回答了这个问题:您只需将范围相加即可。 (它们不相交以排除 UTF-16 的代理项)。
汤姆-谢谢你的评论!我不知道这些限制。我看到了 table 3-7ran the numbers,看起来有 1,083,392 个可能的有效序列。
这是一个准确的答案。其他答案刚刚停在 2^21 并忘记了可能的其余组合。
是的,理论上有 2^7 + 2^11 + 2^16 + 2^21 个符号,但其中很多是 UTF8 规则无效的,所以最后 < 2^21。 UTF8 必须编码 1114112 个 Unicode 符号,2^21 就足够了。尽管许多人忘记了符号组合——变音符号修饰符肤色修饰符零宽度连接符标志 等 UTF8 符号为 1-4 个字节,但这些符号的组合可能是 6/8/20/... 字节,可以表达更多“可见”符号
d
deceze

UTF-8 是一种可变长度编码,每个字符至少 8 位。具有较高代码点的字符将占用最多 32 位。


这是误导。您可以拥有的最长代码点是 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx,因此只有 21 位可用于编码实际字符。
我说过代码点最多可能需要 32 位进行编码,我从未声称(通过归纳)您可以在 32 位 UTF-8 中编码 2^32 个字符。但这没有实际意义,因为您可以使用 UTF-8 编码所有现有的 Unicode 字符,如果将 UTF-8 拉伸到 48 位(存在但已弃用),您可以编码更多,所以我不确定是什么误导点是。
Z
ZZ-bb

引自维基百科:“UTF-8 使用一到四个 8 位字节(在 Unicode 标准中称为“八位字节”)对 Unicode 字符集中的 1,112,064 个代码点中的每一个进行编码。”

一些链接:

http://www.utf-8.com/

http://www.joelonsoftware.com/articles/Unicode.html

http://www.icu-project.org/docs/papers/forms_of_unicode/

http://en.wikipedia.org/wiki/UTF-8


J
Jukka K. Korpela

查看 Unicode 标准和相关信息,例如他们的常见问题解答条目 UTF-8 UTF-16, UTF-32 & BOM。这并不是一帆风顺,但它是权威信息,您可能在其他地方读到的关于 UTF-8 的大部分内容都是值得怀疑的。

“UTF-8”中的“8”与以位为单位的代码单元的长度有关。代码单元是用于编码字符的实体,不一定是简单的一对一映射。 UTF-8 使用可变数量的代码单元对字符进行编码。

可以用 UTF-8 编码的字符集合与 UTF-16 或 UTF-32 完全相同,即所有 Unicode 字符。它们都对整个 Unicode 编码空间进行编码,甚至包括非字符和未分配的代码点。


J
James V. Fields

虽然我同意 mpen 对当前最大 UTF-8 代码 (2,164,864) 的看法(如下所列,我无法评论他的内容),但如果您删除 UTF-8 的 2 个主要限制,他会下降 2 个级别:只有 4 个字节限制和代码 254 和 255 不能使用(他只去掉了 4 字节限制)。

起始代码 254 遵循起始位的基本排列(多位标志设置为 1,计数 6 个 1,终端 0,无备用位)为您提供 6 个额外字节可使用(6 个 10xxxxxx 组,额外 2^ 36 个代码)。

起始代码 255 不完全遵循基本设置,没有终端 0,但使用了所有位,为您提供了 7 个额外字节(多位标志设置为 1,计数为 7 个 1,并且没有终端 0,因为使用了所有位; 7 个 10xxxxxx 组,额外的 2^42 个代码)。

将这些添加到最终的最大可呈现字符集为 4,468,982,745,216。这比当前使用的所有字符、旧的或死的语言以及任何被认为丢失的语言都要多。天使或天体脚本有人吗?

除了 254 和 255:128-191 以及其他一些代码之外,UTF-8 标准中还有一些单字节代码被忽略/忽略。有些是由键盘在本地使用的,示例代码 128 通常是一个删除退格键。由于一个或多个原因 (https://en.wikipedia.org/wiki/UTF-8#Invalid_byte_sequences),其他起始代码(和相关范围)无效。


D
Display name

Unicode 与 UTF-8 紧密结合。 Unicode 特别支持 2^21 个代码点(2,097,152 个字符),这与 UTF-8 支持的代码点数量完全相同。两个系统都为代码点等保留相同的“死”空间和受限区域。...as of June 2018 the most recent version, Unicode 11.0, contains a repertoire of 137,439 characters

来自 unicode 标准。 Unicode FAQ

Unicode 标准对 U+0000..U+10FFFF 范围内的字符进行编码,这相当于 21 位代码空间。

来自 UTF-8 维基百科页面。 UTF-8 Description

由于 2003 年将 Unicode 代码空间限制为 21 位值,UTF-8 被定义为将代码点编码为 1 到 4 个字节,...


21 位四舍五入。 Unicode 支持 1,114,112 个代码点(U+0000 到 U+10FFFF),就像它说的那样。 (有时被描述为 65536 的 17 架飞机。)
@TomBlodget,你是对的。从这次讨论中最相关的收获是 UTF-8 可以对 Unicode 标准中当前定义的所有点进行编码,并且很可能在未来相当长的一段时间内都可以这样做。