Unicode UTF-8是如何做到的;可变宽度编码;工作

Unicode UTF-8是如何做到的;可变宽度编码;工作,unicode,utf-8,character-encoding,multibyte,Unicode,Utf 8,Character Encoding,Multibyte,unicode标准中有足够的代码点,您需要4个字节来存储它们。这就是UTF-32编码的作用。然而,UTF-8编码通过使用一种叫做“可变宽度编码”的东西,以某种方式将这些压缩到更小的空间中 事实上,它设法在一个字节内表示US-ASCII的前127个字符,看起来与真正的ASCII完全相同,因此您可以将大量ASCII文本解释为UTF-8,而无需对其进行任何操作。巧妙的把戏。那么它是如何工作的呢 我在这里要问和回答我自己的问题,因为我只是读了一点书来弄明白,我想这可能会为其他人节省一些时间。另外,如果我

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

事实上,它设法在一个字节内表示US-ASCII的前127个字符,看起来与真正的ASCII完全相同,因此您可以将大量ASCII文本解释为UTF-8,而无需对其进行任何操作。巧妙的把戏。那么它是如何工作的呢


我在这里要问和回答我自己的问题,因为我只是读了一点书来弄明白,我想这可能会为其他人节省一些时间。另外,如果我弄错了,也许有人可以纠正我

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

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
因为你可以从前几位看出你看到的是什么类型的字节,所以即使某些东西在某个地方损坏了,你也不会丢失整个序列

UTF-8是另一种存储系统 您的Unicode代码点字符串, 那些神奇的U+数字,在记忆中 使用8位字节。在UTF-8中,每个 0-127之间的代码点存储在 单字节。仅代码点128和128 上面是用2,3存储的,事实上, 最多6个字节

摘自

的内容是此处的最终权威,并拥有所有解释


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

直接Unicode不需要32位来编码其所有代码点。他们曾经声称有那么多可能的代码点,但在UTF-8起飞后,他们有意将自己限制在21位,这样UTF-8每个字符就永远不会超过4个字节。Unicode目前只需要17位来保存所有可能的代码点。如果没有这一限制,UTF-8可以达到每个字符6字节。@Warren:基本准确,但Unicode是21位代码(U+0000到U+10FFFF)。@Warren:4字节限制的UTF-8可以支持最多U+1FFFF。对U+10FFFF的限制是为了UTF-16而制定的。@dan04对于UTF-16如何限制U+10FFFF,我们有什么简单的解释吗?很高兴了解更多信息。@A-letubby:因为UTF-16“代理”代码的分配方式是有1024个前导代理和1024个尾随代理(它们只能成对使用),以便在BMP之外增加2^20(约一百万)个字符。加上BMP中可用的2^16个字符,这使得0x110000个字符成为可能;Wikipedia页面仅显示每个字符1..4个字节。正如我前面所说,当UTF-8首次创建时,Unicode声称代码点最多为32位,这并不是因为他们真的需要它,只是因为32位是一个方便的值,而且它们已经超过了之前16位字符的限制。在UTF-8被证明很流行之后,他们选择将最大代码点数限制在2^21,这是UTF-8方案中4个字节可以编码的最大值。Unicode中还有不到2^17个字符,因此我们可以使用此新方案将Unicode中的字符数增加四倍以上。好的,但不是OP提出的解释。这并不是在回答问题。故事还不止于此-因为编码必须是字符的最短编码,例如,这意味着字节0xC0和0xC1不能出现在UTF-8中;事实上,0xF5..0xFF也不能。请参阅上的UTF-8常见问题解答,或者为什么不能只使用一个字符来表示下一个字符是continuation?如果我们得到的是3字节字符,那么它将类似于:
1xxxxxxx 1xxxxxxx 0xxxxxxx
,因此会浪费更少的空间。@Soaku它使UTF-8成为所谓的“自同步”代码。这意味着,如果由于错误,序列的某些部分丢失,则可以检测到该部分并丢弃任何被篡改的内容。如果您读取一个以10xx开头的字节,并且前面没有“start”字节,您可以丢弃它,因为它没有意义。如果您有一个像您描述的那样的系统,并且第一个字节中的一个丢失了,那么您可能会得到一个不同的、有效的字符,并且没有任何类型的错误指示。它还可以很容易地找到下一个有效字符,并纠正丢失的“continuation”字节。嗯,我真傻,我以为Unicode标准是UTF-8Unicode标准定义Unicode本身的最终权威。它没有定义各种方法,无论是现在还是将来,都可以用于对unicode文本进行编码,以实现各种目的(如存储和传输)。UTF-8是其中一种方法,上述参考是指定义UTF-8的文件。RFC3629,第3页,第3节。上面写着“UTF-8是由Unicode标准定义的”。我在Unicode.org上寻找链接,找到了D92(也就是D86)的具体定义。我不知道这个链接在新版本发布时会在多大程度上有用,但我想他们希望在不同版本之间保持节和定义标识符的稳定。