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

dsi*_*ard 103 unicode utf-8 character-encoding multibyte

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

实际上,它设法在一个字节中代表US-ASCII的前127个字符,它看起来与真正的ASCII完全相同,因此您可以将许多ascii文本解释为UTF-8而不对其执行任何操作.干净的把戏.那么它是怎样工作的?

我将在这里提出并回答我自己的问题,因为我只是做了一些阅读以弄清楚它并且我认为它可能会节省其他人一些时间.如果我有一些错误,也许有人可以纠正我.

dsi*_*ard 122

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

0xxx xxxx    A single-byte US-ASCII code (from the first 127 characters)
Run Code Online (Sandbox Code Playgroud)

多字节代码点每个都以几位开始,基本上说"嘿,你还需要读取下一个字节(或两个或三个)来弄清楚我是什么." 他们是:

110x xxxx    One more byte follows
1110 xxxx    Two more bytes follow
1111 0xxx    Three more bytes follow
Run Code Online (Sandbox Code Playgroud)

最后,这些起始代码后面的字节都如下所示:

10xx xxxx    A continuation of one of the multi-byte characters
Run Code Online (Sandbox Code Playgroud)

既然你可以从前几位看出你正在看什么类型的字节,那么即使某些东西被破坏了,你也不会丢失整个序列.

  • 故事还有更多 - 因为编码必须是字符的最短编码,这最终意味着字节0xC0和0xC1不能出现在UTF-8中,例如; 事实上,它们都不能是0xF5..0xFF.请参阅http://unicode.org/faq/utf_bom.html上的UTF-8常见问题解答,或http://www.unicode.org/versions/Unicode5.2.0/ch03.pdf (13认同)
  • @Soaku它使UTF-8成为所谓的"自同步"代码.这意味着如果由于错误而缺少部分序列,则可以检测到并丢弃任何乱码.如果你读取一个以10xx开头的字节,并且没有前面的"开始"字节,你可以丢弃它,因为它没有意义.如果您有一个类似于您描述的系统,并且丢失了第一个字节之一,那么最终可能会得到一个不同的有效字符,并且不会出现任何错误.它还可以轻松找到下一个有效字符,并纠正丢失的"延续"字节. (6认同)
  • 为什么不能只使用一个字符来表示“下一个字符是延续”?如果我们得到 3 个字节的字符,那么它将类似于:`1xxxxxxx 1xxxxxxx 0xxxxxxx`,这样会浪费更少的空间。 (2认同)

azh*_*lov 9

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

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

  • Unicode标准定义了Unicode本身.它没有定义今天和未来的各种方法,可用于为各种目的(例如存储和传输)编码unicode文本.UTF-8是其中一种方法,上面的参考文献是定义它的文档. (6认同)
  • RFC3629,第 3 页,第 3 节说“UTF-8 由 Unicode 标准定义”。 (2认同)