utf-8:如何从丢失位恢复?

时间:2018-01-04 03:24:00

标签: encoding utf-8 character-encoding utf-16

来自Wikipedia

  

如果字节流受到损坏,则某些编码会比其他编码恢复得更好。 UTF-8和UTF-EBCDIC在这方面是最好的,因为它们总是可以在下一个代码点开始时重新同步;

     

...

     

UTF-16和UTF-32将通过在下一个良好的代码点上重新同步来处理损坏的(改变的)字节,但奇数个丢失或伪字节(八位字节)将使所有后续文本乱码

我不太明白为什么当发生损坏时,UTF-8比UTF-16效果更好。 “奇数”是什么意思?这是1(字节流)中的0101010111101吗?

此外,当没有奇数丢失或伪字节(八位位组)发生时,我能说UTF-16的恢复性能和UTF-8一样好吗?

在使用UTF-8或UTF-16时,有没有人能说明系统如何从比特错误中恢复?

2 个答案:

答案 0 :(得分:0)

此文档引用是指在丢失一些代码点后恢复流,而不是纠正在传输过程中出现问题的字符。

这意味着简单:如果你错过utf-8流中的一个或多个字节,只要下一个字节是新代码点(通常是一个字符)的开头,你就可以恢复你的文本从那里。

在utf-16中,所有字符都是2个字节长,如果你错过了一个字节,那么所有后续字节将被放错位置,没有更高级别的校正,没有其他代码点对于该流是正确的。

为了可视化,我们可以在Python3交互模式中执行以下操作:

In [19]: a = "Resumé for mr. Fernando"

In [20]: b = a.encode("utf-8"); b = b[:3] + b[4:] 

In [21]: print (b.decode("utf-8"))
Resmé for mr. Fernando

In [22]: b = a.encode("utf-16"); b = b[:10] + b[11:] 

In [23]: print (b.decode("utf-16", errors="replace"))
Resu 昀漀爀 洀爀⸀ 䘀攀爀渀愀渀搀漀�

(Python中用于那些不熟悉的切片符号表示[<begin (inclusive)>: <end (exclusive)>]作为位置。任何留空的参数都被认为是切片序列的开头或结尾)

为什么&#34;奇怪&#34;在这一点上应该是显而易见的:如果你错过偶数个字节,解码系统仍然会尝试在字符边界处进行解码 - 使用奇数,所有字符边界都将是不正确的

答案 1 :(得分:0)

魔术隐藏在编码结构中。在UTF-8结构中,UTF-8编码字节的所有起始字节不能被不是起始字节的字节错位。但是,UTF-16中的情况并非如此。

UTF-8结构 UTF-8 structure 让我们模拟一个接收UTF-8编码字节作为输入和输出代码点的魔术机如何在3个字节长的UTF-8编码字节中丢失一个字节时起作用。

比如说,来自两个字符一二的UTF-8编码字节是e4b880)和e4ba8c)。现在机器读取e411100100,知道以下代码点是一个3字节长的代码点。不幸的是,错过了以下字节b8。接下来,读取80。然后,读取的第一个字节,即e4。但是,e4并不适合规则:当涉及3字节长码点时,根据上表,字节3需要以10开头。现在机器知道缺少一些字节并且代码点被破坏。它会尝试四处寻找正确的解码起点。显然,下一个字节ba不是一个好的开始,因为它不适合上表中的任何字节1。然后它将回顾过去,发现前一个字节e4是一个很好的解码起始字节。

在UTF-16中,由于UTF-16无法判断它是否为起始字节,因此字节可能会被不是起始字节的字节错误替换。