kno*_*dge 8 unicode encoding character utf-8
据我所知,UTF-8 是一种变长编码,即一个字符可以表示为 1 个字节、2 个字节、3 个字节或 4 个字节。
例如,Unicode 字符 U+00A9 = 10101001 以 UTF-8 编码为
110 00010 10 101001,即0xC2 0xA9
第一个字节中的前缀 110 表示该字符用两个字节存储(因为我在前缀 110 中数了两个直到零)。
以下字节中的前缀以 10 开头
一个 4 字节的 UTF-8 编码看起来像
11110 xxx 10 xxxxxx 10 xxxxxx 10 xxxxxx
前缀 11110(四个一和零)表示四个字节,依此类推。
现在我的问题:
为什么在以下字节中使用前缀 10?这样的前缀有什么好处?如果在以下字节中没有 10 前缀,我可以多使用 3*2=6 位,如果我写:
1111 0000 xxxxxxxx xxxxxxxx xxxxxxxx
历史上有很多关于 UTF-8 编码的建议。其中一个在以下字节中不使用前缀,另一个名为FSS-UTF使用前缀1
Number First Last
of bytes code point code point
1 U+0000 U+007F 0xxxxxxx
2 U+0080 U+07FF 110xxxxx 10xxxxxx
3 U+0800 U+FFFF 1110xxxx 10xxxxxx 10xxxxxx
4 U+10000 U+1FFFFF 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
5 U+200000 U+3FFFFFF 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
6 U+4000000 U+7FFFFFFF 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
Run Code Online (Sandbox Code Playgroud)
然而最后使用的前缀的新的编码10选择
贝尔实验室 Plan 9 操作系统小组的 Ken Thompson 进行了修改,使其比之前的提案在位效率上有所降低,但至关重要的是允许它自同步,让阅读器从任何地方开始并立即检测字节序列边界。
正如其他人提到的,新编码最明显的优点是自同步。它允许读者轻松找到字符边界,因此可以快速跳过任何丢弃的字节,并且还可以在给定字符串中的任何字节索引的情况下立即找到当前/上一个/下一个字符。如果索引字节以 10 开头,则只是一个中间字节,只需向后或向前查找周围字符的开头即可;否则,如果它以 0 或 11 开头,则它是字节序列的开始
这个属性非常重要,因为在像Shift-JIS这样没有自同步的糟糕设计的编码中,阅读器必须维护一个字符偏移表,或者它必须从头开始重新解析数组以编辑字符串。在用于日语的 DOS/V(使用 Shift-JIS)中,可能是由于内存量有限,没有使用该表,因此每次按下Backspace操作系统时,都需要从一开始就重新知道删除了哪个字符。无法像 UTF-8 那样获得前一个字符的长度
UTF-8 的前缀特性还允许旧的 C 字符串搜索函数无需任何修改即可工作,因为搜索字符串的字节序列永远不会出现在另一个有效的 UTF-8 字节序列的中间。在 Shift-JIS 或其他非自同步编码中,您需要专门的搜索功能,因为起始字节可以是另一个字符的中间字节
以上一些优点也是UTF-16所共有的
由于高代理 (0xD800–0xDBFF)、低代理 (0xDC00–0xDFFF) 和有效 BMP 字符 (0x0000–0xD7FF、0xE000–0xFFFF) 的范围不相交,代理不可能匹配 BMP 字符,或者两个相邻的代码单元看起来像一个合法的代理对。这大大简化了搜索。这也意味着 UTF-16 在 16 位字上是自同步的:可以确定一个代码单元是否开始一个字符,而无需检查早期的代码单元(即代码单元的类型可以通过它所在的值的范围来确定)下降)。UTF-8 具有这些优点,
多字节字符的所有后续字节都以二进制 10 开头,表示它们是后续字节。
如果传输的某些部分损坏和/或丢失,这允许重新同步。例如,如果多字节序列的第一个字节丢失,您仍然可以找出下一个字符的开始位置。
如果后续字节可以取任何值,则无法将后续字节与单字节编码字符区分开来。
| 归档时间: |
|
| 查看次数: |
1226 次 |
| 最近记录: |