如果 UTF-8 是 8 位,是不是意味着最多只能有 256 个不同的字符?
前 128 个代码点与 ASCII 中的相同。但它说UTF-8可以支持多达百万个字符?
这是如何运作的?
UTF-8 并不总是使用一个字节,它是 1 到 4 个字节。
前 128 个字符(US-ASCII)需要一个字节。接下来的 1,920 个字符需要两个字节来编码。这涵盖了几乎所有拉丁字母的其余部分,以及希腊语、西里尔语、科普特语、亚美尼亚语、希伯来语、阿拉伯语、叙利亚语和塔纳字母,以及组合变音符号。其余基本多语言平面中的字符需要三个字节,其中包含几乎所有常用字符[12],包括大多数中文、日文和韩文 [CJK] 字符。 Unicode 其他平面中的字符需要四个字节,其中包括不太常见的 CJK 字符、各种历史文字、数学符号和表情符号(象形符号)。
来源:Wikipedia
UTF-8 每个字符使用 1-4 个字节:一个字节用于 ascii 字符(前 128 个 unicode 值与 ascii 相同)。但这只需要 7 位。如果设置了最高(“符号”)位,则表示多字节序列的开始;设置的连续高位的数量表示字节数,然后是 0,其余位对值有贡献。对于其他字节,最高两位是 1 和 0,其余 6 位是值。
因此,一个四字节序列将从 11110... 开始(并且 ... = 三个位的值),然后三个字节,每个 6 位的值,产生一个 21 位的值。 2^21 超过了 unicode 字符的个数,所以所有的 unicode 都可以用 UTF8 表示。
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
根据 this table* UTF-8 应该支持:
231 = 2,147,483,648 个字符
但是,RFC 3629 限制了可能的值,所以现在我们是 capped at 4 bytes,这给了我们
221 = 2,097,152 个字符
请注意,这些字符中有很大一部分是“保留”用于自定义使用的,这对于图标字体来说实际上非常方便。
* 维基百科使用了一个 6 字节的表格——他们已经更新了这篇文章。
2017-07-11:更正了重复计算用多个字节编码的相同代码点
0xxxxxxx
提供 7 个可用位,110xxxxx 10xxxxxx
提供 11 个以上 - 没有重叠。第一个字节在第一种情况下以 0
开头,在第二种情况下以 1
开头。
00000001
存储什么代码点以及 11000000 100000001
存储什么?
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 个字符)大得多。
更新
我最初的计算是错误的,因为它没有考虑额外的规则。有关更多详细信息,请参阅对此答案的评论。
2^21
并忘记了可能的其余组合。
2^7 + 2^11 + 2^16 + 2^21
个符号,但其中很多是 UTF8 规则无效的,所以最后 < 2^21。 UTF8 必须编码 1114112
个 Unicode 符号,2^21
就足够了。尽管许多人忘记了符号组合——变音符号修饰符、肤色修饰符、零宽度连接符、标志 等 UTF8 符号为 1-4 个字节,但这些符号的组合可能是 6/8/20/... 字节,可以表达更多“可见”符号
UTF-8 是一种可变长度编码,每个字符至少 8 位。具有较高代码点的字符将占用最多 32 位。
11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
,因此只有 21 位可用于编码实际字符。
引自维基百科:“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
查看 Unicode 标准和相关信息,例如他们的常见问题解答条目 UTF-8 UTF-16, UTF-32 & BOM。这并不是一帆风顺,但它是权威信息,您可能在其他地方读到的关于 UTF-8 的大部分内容都是值得怀疑的。
“UTF-8”中的“8”与以位为单位的代码单元的长度有关。代码单元是用于编码字符的实体,不一定是简单的一对一映射。 UTF-8 使用可变数量的代码单元对字符进行编码。
可以用 UTF-8 编码的字符集合与 UTF-16 或 UTF-32 完全相同,即所有 Unicode 字符。它们都对整个 Unicode 编码空间进行编码,甚至包括非字符和未分配的代码点。
虽然我同意 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),其他起始代码(和相关范围)无效。
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 个字节,...