UTF-8“可变宽度编码”如何工作?


110

unicode标准中有足够的代码点,您需要4个字节来存储它们。这就是UTF-32编码的作用。然而,UTF-8编码通过使用一种称为“可变宽度编码”的方式将它们压缩到更小的空间中。

实际上,它设法在一个字节中代表了US-ASCII的前127个字符,这看起来与真实的ASCII完全一样,因此您可以将许多ascii文本解释为UTF-8,而无需对其进行任何处理。整洁的把戏。那么它是怎样工作的?

我将在这里问和回答我自己的问题,因为我只是做了一些阅读来弄清楚这个问题,我认为这可能会节省一些时间。另外,如果我有一些错误,也许有人可以纠正我。


8
直统一并不会需要32位编码所有的代码点。他们曾经声称拥有许多可能的代码点,但是在UTF-8起飞之后,他们有意将自己限制为21位,因此UTF-8永远不会超过每个字符4个字节。Unicode当前仅需要17位即可容纳所有可能的代码点。没有此限制,UTF-8每个字符可以达到6个字节。
沃伦·杨

@Warren:大部分都是准确的,但Unicode是21位代码(U + 0000至U + 10FFFF)。
乔纳森·勒夫勒

2
@沃伦:限制为4字节的UTF-8最多可以支持U + 1FFFFF。为了UTF-16,对U + 10FFFF进行了限制。
dan04 2011年

@ dan04关于UTF-16如何将其限制为U + 10FFFF,我们是否有任何简单的解释?很高兴了解更多有关此的信息。
A-letubby '16

@ A-letubby:因为分配了UTF-16“代理”代码,所以有1024个前导代理和1024个尾随代理(它们只能成对使用),因此要增加2 ^ 20(约一百万个)字符在BMP之外可用。添加到BMP中可用的2 ^ 16个字符后,这使0x110000个可能的字符成为可能。
dan04 '02

Answers:


129

每个字节以几位开头,告诉您它是单字节代码点,多字节代码点还是多字节代码点的延续。像这样:

0xxx xxxx    A single-byte US-ASCII code (from the first 127 characters)

每个多字节代码点都以几个比特开头,这些比特本质上说“嘿,您还需要读取下一个字节(或两个或三个)以弄清我是什么。” 他们是:

110x xxxx    One more byte follows
1110 xxxx    Two more bytes follow
1111 0xxx    Three more bytes follow

最后,这些起始代码后面的字节都看起来像这样:

10xx xxxx    A continuation of one of the multi-byte characters

因为您可以从头几位知道要查看的字节类型,所以即使某些地方出现错误,也不会丢失整个序列。


14
故事的意义远不止于此-因为编码必须是字符的最短编码,这最终意味着字节0xC0和0xC1不能出现在UTF-8中;例如:实际上,0xF5..0xFF都不能。请参阅unicode.org/faq/utf_bom.htmlunicode.org/versions/Unicode5.2.0/ch03.pdf中
Jonathan Leffler

2
为什么不能只用一个字符说呢next char is continuation?如果我们得到了3个字节的字符,那么它将是:1xxxxxxx 1xxxxxxx 0xxxxxxx,这样会浪费更少的空间。

9
@Soaku使UTF-8成为所谓的“自同步”代码。这意味着如果由于错误而丢失了序列的某些部分,则可以检测到该部分并丢弃任何乱码。如果读取的字节以10xx开头,并且前面没有“开始”字节,则可以将其丢弃,因为它毫无意义。如果您有一个如上所述的系统,并且第一个字节丢失了,您可能会得到一个不同的有效字符,而没有任何错误的迹象。这也将使查找下一个有效字符变得容易,并对丢失的“连续”字节进行校正。
htmlcoderexe

9

RFC3629-UTF-8(ISO 10646的转换格式)是此处的最终授权,并具有所有解释。

简而言之,UTF-8编码的1到4字节序列的每个字节中的几个位(代表单个字符)用于指示它是尾随字节还是前导字节,如果是,则跟随其后是多少个字节。其余位包含有效载荷。


1
Ummmm,我傻,我以为Unicode标准是在UTF-8的最终权威
约翰·马金

6
Unicode标准定义了Unicode本身。它没有定义现在和将来的各种方法,这些方法可用于出于各种目的(例如存储和传输)对unicode文本进行编码。UTF-8是这些方法之一,上面的参考是对定义它的文档的引用。
azheglov 2010年

1
RFC3629,第3页,第3节。说“ UTF-8由Unicode标准定义”。
约翰·马钦

追逐unicode.org上的链接将我带到Unicode标准的3.9节,特别是定义D92(以及切向D86)。我不知道在发布新版本时此链接将在多大程度上有用,但我可以想象他们希望保持各个版本中的节和定义标识符稳定。
Tripleee '18

4

UTF-8是另一个使用8位字节将Unicode代码点的字符串(那些神奇的U +数字)存储在内存中的系统。在UTF-8中,从0-127的每个代码点都存储在一个字节中。实际上,只有代码点128和更高的代码点才使用2、3(最多6个字节)存储。

摘自《绝对最低要求》每个软件开发人员绝对,肯定必须了解Unicode和字符集(无借口!)


那是一篇很好的文章,但是就序列的最大长度而言,Joel似乎是错误的。维基百科页面仅显示每个字符1..4字节。
放松

4
就像我在上面说的那样,当首次创建UTF-8时,Unicode声称最多可以使用32位的代码点,这并不是因为他们确实需要它,而是因为32位是一个方便的值,并且它们已经超出了范围。以前的16位字符限制。在证明UTF-8流行之后,他们选择将最大代码点数限制为2 ^ 21,这是可以使用4个字节的UTF-8方案进行编码的最大值。Unicode中的字符数仍然少于2 ^ 17,因此,使用这种新方案,我们可以将Unicode中的字符数增加两倍以上。
沃伦·杨

好的,但是OP要求的解释不行。
Nishant 2014年

2
这没有回答问题。
Koray Tugay,2015年
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.