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


97

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

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

这是如何运作的?


2
如果可以,请重新评估该问题,因为所有答案都是错误的。读我的答案:stackoverflow.com/a/45042566/124486
Evan Carroll

在Unicode的UTF-8,UTF-16,UTF-32编码中,数字是其代码单位中的位数,其中一个或多个编码Unicode代码点。
汤姆·布洛杰特

1
我不久前回答了这个问题,试图将其弄清楚:如果您将它与选择的答案权衡一下,那就太好了,因为从字面上看,这只是一个维基百科引用,并不能说明全部内容(希望我的更新是更加清晰了)
埃文·卡罗尔

Answers:


135

UTF-8不会一直使用一个字节,而是1到4个字节。

前128个字符(US-ASCII)需要一个字节。

接下来的1,920个字符需要两个字节进行编码。这涵盖了几乎所有拉丁字母的其余部分,以及希腊语,西里尔字母,科普特语,亚美尼亚语,希伯来语,阿拉伯语,叙利亚语和塔纳语字母,以及组合变音符号。

在基本多语言平面的其余部分中,字符需要三个字节,其中几乎包含了所有常用的字符[12],包括大多数中文,日文和韩文[CJK]字符。

Unicode其他平面中的字符需要四个字节,其中包括较少见的CJK字符,各种历史脚本,数学符号和表情符号(象形符号)。

资料来源:维基百科


嗨@zwippie我是新来的。有些东西我不明白。BMP使用2个字节,您说是3个?我错了吗?
chiperortiz

1
@ chiperortiz,BMP的确是16位的,因此可以将其编码为UTF-16,每个字符的长度恒定(UTF-16还支持超过16位,但这是一个困难的实践,许多实现都不支持它)。但是,对于UTF-8,您还需要对其编码多长时间,因此会丢失一些位。这就是为什么您需要3个字节来编码完整的BMP的原因。这可能看起来很浪费,但是请记住,UTF-16始终使用2个字节,但是对于大多数基于拉丁语的语言字符,UTF-8每个字符使用一个字节。使它紧凑两倍。
sanderd17 '19

OP的问题的主旨与为什么将其称为UTF- 8有关 -并不能真正回答这一问题。
jbyrd

40

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

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


@NickL。不,我的意思是3个字节。在该示例中,如果多字节序列的第一个字节以1111开始,则第一个1表示它多字节序列的开始,然后其后的连续1的数量表示该序列中其他字节的数量(因此第一个字节将以110、1110或11110开始)。
CodeClown42 '16

在RFC 3629中找到了您的单词的证明。tools.ietf.org/ html/ rfc3629 #section-3。但是,我不明白为什么我需要在第二个字节的开头110xxxxx 10xxxxxx放置“ 10”?为什么不只是110xxxxx xxxxxxxx?
kolobok

3
softwareengineering.stackexchange.com/questions/262227/…中找到了答案。仅出于安全原因(万一流中间的单个字节损坏)
kolobok

@kolobok啊。为了安全起见,您可以将3个字节的21位值编码(3位表示长度,再加上21位)。:D至少WRT西方语言可能没有那么大的意义。
CodeClown42

我猜想NickL问过这个问题,但是如果...代表后续字节而不是位,那么第一个字节中的其余位又如何了?
c6754 '19

27

根据此表 * UTF-8 应该支持:

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

但是,RFC 3629限制了可能的值,所以现在我们限制为4个字节,这使我们

2 21 = 2,097,152个字符

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

* Wikipedia用来显示一个6字节的表格-自此以后,他们就对文章进行了更新。

2017年7月11日:更正了对重复使用多个字节编码的相同代码点的重复计数的问题


这个答案是重复计算可能的编码数量。计算完所有2 ^ 7后,就无法再以2 ^ 11、2 ^ 16等进行计数。可能的正确编码数是2 ^ 21(尽管当前未使用全部)。
吉米

@吉米你确定我在重复计数吗?0xxxxxxx给出7个可用位,再110xxxxx 10xxxxxx给出11个-没有重叠。第0一种情况的第一个字节以1第二种情况开头。
mpen

@mpen那么00000001存储什么代码点以及11000000 100000001存储什么?
埃文·卡罗尔

1
@EvanCarroll嗯。。。没有意识到有多种方法可以编码相同的代码点。
mpen

1
我继续尝试自己回答这个问题,看看您是否认为这是更好的解释并回答了这个问题:stackoverflow.com/a/45042566/124486
Evan Carroll

21

Unicode与UTF-8

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

统一码

Unicode用“平面”指定每架飞机上载有2 个16码点。Unicode中有17个平面。共计17 * 2^16代码点。第一个平面,即平面0或BMP,在承载重量方面是特殊的。

除了解释所有细微差别外,我只引用飞机上的上述文章。

这17架飞机可以容纳1,114,112个代码点。其中,有2,048个是代理人,有66个是非字符,还有137,468个供私人使用,剩下974,530个用于公共任务。

UTF-8

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

UTF-8使用的编码方案的最大限制是2 31个代码点(32,768个平面),即使限制为4个字节,也可以编码2个21个代码点(32个平面)。[3] 由于Unicode将代码点限制为可以由UTF-16编码的17个平面,因此0x10FFFF以上的代码点在UTF-8和UTF-32中无效。

因此,您可以看到您可以将不是有效Unicode的内容放入UTF-8。为什么?因为UTF-8可以容纳Unicode甚至不支持的代码点。

UTF-8即使有四个字节的限制,也支持2 21个代码点,这远远超过了17 * 2^16


19

UTF-8可能会编码2,164,864个“字符”。

这个数字是2 ^ 7 + 2 ^ 11 + 2 ^ 16 + 2 ^ 21,它来自编码的工作方式:

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

  • 2个字节的字符具有11个编码位 110xxxxx 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
您的数学不遵守UTF-8规则,即仅允许最短的代码单元序列编码一个代码点。因此,00000001对U + 0001有效,但11110000 10000000 10000000 10000001无效。参考:表3-7。格式正确的UTF-8字节序列。此外,表格直接回答了这个问题:您只需将范围相加即可。(它们是不相交的,以排除UTF-16的代理人)。
汤姆·布洛杰特

汤姆-感谢您的评论!我没有意识到这些限制。我看到了表3-7运行了数字,看起来有1,083,392个可能的有效序列。
鲁本·雷耶斯

6

UTF-8是可变长度编码,每个字符最少 8位。
具有更高代码点的字符最多需要32位。


2
这是误导。您可以拥有的最长代码点是11110xxx 10xxxxxx 10xxxxxx 10xxxxxx,因此只能使用21位来编码实际字符。
鲍里斯

5
我说过代码点最多可能需要32位才能编码,但我从未宣称(通过归纳法)您可以在32位UTF-8中编码2 ^ 32个字符。但这很不实际,因为您可以将所有现有的Unicode字符编码为UTF-8,并且如果将UTF-8扩展为48位(存在但已弃用),则可以进行更多编码,所以我不确定误导点是。
deceze


2

查看Unicode标准和相关信息,例如FAQ条目,UTF-8 UTF-16,UTF-32和BOM。这并非一帆风顺,而是权威信息,您可能在其他地方所读到的有关UTF-8的许多内容都值得商question。

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

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


1

尽管我同意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)而无效。


0

Unicode与UTF-8紧密相连。Unicode特别支持2 ^ 21个代码点(2,097,152个字符),这与UTF-8支持的代码点数完全相同。两种系统都保留相同的“死区”空间和代码点等限制区域。...截至2018年6月,最新版本Unicode 11.0包含137,439个字符

来自unicode标准。 Unicode常见问题

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

从UTF-8 Wikipedia页面。 UTF-8说明

由于在2003年将Unicode代码空间限制为21位值,因此定义了UTF-8以将代码点编码为一到四个字节,...


四舍五入为21位。Unicode表示支持1,114,112个代码点(U + 0000至U + 10FFFF)。(有时被描述为17架65536。)
汤姆·布洛杰特

@TomBlodget,你是​​对的。这次讨论最相关的一点是,UTF-8可以对Unicode标准中所有当前定义的点进行编码,并且很可能在相当长的一段时间内能够实现。
显示名称
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.