ChatGPT解决这个技术问题 Extra ChatGPT

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

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

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

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

直接 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+1FFFFF。对 U+10FFFF 的限制是为了 UTF-16。
@dan04 对于 UTF-16 如何将其限制为 U+10FFFF,我们有什么简单的解释吗?很高兴知道更多关于这一点的信息。
@A-letubby:因为分配了 UTF-16“代理”代码,所以有 1024 个前导代理和 1024 个尾代理(它们只能成对使用),所以要增加 2^20(大约一百万)个字符在 BMP 之外可用。添加到 BMP 中可用的 2^16 个字符,这使得 0x110000 个可能的字符。

A
André Chalella

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

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

由于您可以从前几位中分辨出您正在查看的字节类型,因此即使某处发生了损坏,您也不会丢失整个序列。


故事远不止这些——因为编码必须是字符的最短编码,这意味着字节 0xC0 和 0xC1 不能出现在 UTF-8 中,例如;事实上,0xF5..0xFF 也不能。请参阅 unicode.org/faq/utf_bom.htmlunicode.org/versions/Unicode5.2.0/ch03.pdf 的 UTF-8 常见问题解答
为什么不能只使用一个字符来表示 next char is continuation?如果我们得到 3 字节字符,那么它就像:1xxxxxxx 1xxxxxxx 0xxxxxxx,这样浪费的空间就会更少。
@Soaku 它使 UTF-8 成为所谓的“自同步”代码。这意味着如果由于错误导致序列的某些部分丢失,则可以检测到并丢弃任何乱码。如果您读取一个以 10xx 开头的字节,并且没有前面的“开始”字节,您可以将其丢弃,因为它没有意义。如果你有一个像你描述的系统,并且第一个字节丢失了,你可能会得到一个不同的、有效的字符,没有任何错误的迹象。它还可以轻松定位下一个有效字符,以及纠正丢失的“继续”字节。
C
Community

RFC3629 - UTF-8, a transformation format of ISO 10646 是此处的最终权威,并具有所有解释。

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


嗯,我傻了,我认为 Unicode 标准是 UTF-8 的最终权威
Unicode 标准定义了 Unicode 本身。它没有定义今天和未来的各种方法,可用于对 unicode 文本进行编码以用于各种目的(例如存储和传输)。 UTF-8 是其中一种方法,上面的参考是定义它的文档。
RFC3629,第 3 页,第 3 节。说“UTF-8 由 Unicode 标准定义”。
在 unicode.org 上搜索链接将我带到 section 3.9 of the Unicode Standard,特别是定义 D92(以及切线 D86)。我不知道这个链接在新版本发布时会有多大用处,但我想他们希望在不同版本之间保持节和定义标识符的稳定。
A
Andrew

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

摘自The Absolute Minimum Every Software Developer Absolutely, Positively Must Know About Unicode and Character Sets (No Excuses!)


那是一篇好文章,但似乎 Joel 关于序列的最大长度是错误的;维基百科页面仅显示每个字符 1..4 个字节。
正如我上面所说,当 UTF-8 首次创建时,Unicode 声称代码点最高可达 32 位,并不是因为他们真的需要它,只是因为 32 位是一个方便的值,而且他们已经超越了以前的 16 位字符限制。在 UTF-8 被证明很流行之后,他们选择将最大代码点数永远限制为 2^21,这是您可以使用 UTF-8 方案的 4 个字节编码的最大值。 Unicode 中的字符仍然少于 2^17 个,因此我们可以使用这种新方案将 Unicode 中的字符数增加四倍以上。
好的,但不是 OP 要求的解释。
这不是在回答问题。