Unicode 为什么有必要在UTF-8中标记连续字节?

Unicode 为什么有必要在UTF-8中标记连续字节?,unicode,utf-8,character-encoding,utf,Unicode,Utf 8,Character Encoding,Utf,我最近一直在阅读UTF-8可变宽度编码,我发现奇怪的是UTF-8将每个连续字节的前两位指定为10 Range | Encoding -----------------+----------------- 0 - 7f | 0xxxxxx 80 - 7ff | 110xxxx 10xxxxxx 800 - ffff | 1110xxx 10xxxxxx 10xxxxxx 10000 - 10ffff | 11110

我最近一直在阅读UTF-8可变宽度编码,我发现奇怪的是UTF-8将每个连续字节的前两位指定为10

 Range           |  Encoding
-----------------+-----------------
     0 - 7f      |  0xxxxxx
    80 - 7ff     |  110xxxx 10xxxxxx
   800 - ffff    |  1110xxx 10xxxxxx 10xxxxxx
 10000 - 10ffff  |  11110xx 10xxxxxx 10xxxxxx 10xxxxxx
我正在研究其他可能的可变宽度编码,发现通过使用以下方案,存储所有Unicode最多需要3个字节。如果第一位为1,则字符至少再编码一个字节(直到第一位为0为止)


UTF-8中的延续位真的那么重要吗?第二种编码似乎效率更高。

UTF-8具有自我验证功能,前进速度快,后退更容易

自验证:由于序列中的第一个字节指定长度,因此下一个X字节必须适合
10xxxxxx
,否则序列无效。看到一个
10xxxxxx
字节本身就会立即被识别为无效。
您建议的编码没有内置验证

快速前进:如果必须跳过字符,则可以立即跳过由第一个字节确定的X字节,而无需检查每个中间字节

后退更容易:如果必须向后读取字节,可以通过
10xxxxxx
立即识别连续字符。然后,您将能够向后扫描
10xxxxxx
前导字节的
10xxxxxx
字节,而无需扫描前导字节


请参阅Wikipedia。

使用您建议的方案,如果您查看字节编码的0xxxxxxx,您无法判断这是单字节单元0x00..0x7F还是多字节单元的最后一个字节。您必须向后扫描并查看前面的字节才能知道(您必须向后检查两个单元,以查看这是否是2字节或3字节代码点的最后一个字节)。如果您有一个1xxxxxx字节,则无法判断它是多字节单元的第一个字节还是中间字节。同样,你必须向后扫描


相反,UTF-8方案允许您告诉任何非连续字节有多少后续字节是代码点的一部分。对于连续字节,只需向后扫描到起始字节。您还可以进行错误检查;UTF-8中有许多无效序列,这实际上是一个优点。(字节0xC0、0xC1、0xF5..0xFF不能出现在有效的UTF-8中。)

除了前面提到的易于迭代之外:UTF-8旨在使基于ASCII(以及其他UTF-8-unknowledge)的工具能够安全地通过搜索、连接、替换和转义等常见操作进行处理

ASCII兼容性对于互操作和安全性的优势超过了为字符U+0800到U+407F使用额外字节的成本

80-407f | 1xxxxxx 0xxxxxxx

所以有一些东亚多字节编码就是这样做的,有一些不幸的结果,UTF-8特别试图避免

在该方案中,延续字节现在与ASCII重叠,许多ASCII字符对不同的语言和工具具有特殊意义。因此,如果你想说
那是0x80,0x27,它的第二个字节看起来像
,对于任何操纵字节字符串的工具来说,都不支持,也不知道这些数据使用的是建议的编码

提示将用户输入合并到控制流中的所有内容都存在安全漏洞。查询中的SQL注入、网页上的HTML注入、shell脚本中的命令注入等等


(东亚的多字节编码没有这里的这种编码那么糟糕,因为它们没有将ASCII控制码作为延续字节重复使用。例如,按照提议,使用这种编码的文本不能存储在以C null结尾的字符串中。尽管如此,Shift JIS和friends还是造成了一大堆安全漏洞,我们都很高兴能够摆脱它

UTF-8方案允许您从任何代码单元位置恢复预期解码。即使使用我的编码,这也是可能的。从任何任意位置后退,直到找到结束字节(带0),则下一个字节是字符的开头。不是真的:如果您指向
0xxxxxx
字节,我无法判断这是完整的字符还是多字节序列的损坏结尾。(假设我无法返回。)
 Range           |  Encoding
-----------------+-----------------
     0 - 7f      |  0xxxxxx
    80 - 407f    |  1xxxxxx 0xxxxxxx
  4080 - 20407f  |  1xxxxxx 1xxxxxxx 0xxxxxxx