Fol*_*vir 5 python decode utf-8 cesu-8
我为此苦苦挣扎:
b'"\xc2\xb7\xed\xa0\x81\xed\xb1\x96\xed\xa0\x81\xed\xb1\xb1\xed\xa0\x81\xed\xb1\x9d\xed\xa0\x81\xed\xb1\xbe\xed\xa0\x81\xed\xb1\xaf \xed\xa0\x81\xed\xb1\xa9\xed\xa0\x81\xed\xb1\xa4\xed\xa0\x81\xed\xb1\x93\xed\xa0\x81\xed\xb1\xa9\xed\xa0\x81\xed\xb1\x9a\xed\xa0\x81\xed\xb1\xa7\xed\xa0\x81\xed\xb1\x91"@en'
它来自(dbpedia 3.5.1(http://dbpedia.org/page/Shavian_alphabet))的HDT压缩版本(https://github.com/rdfhdt/hdt-cpp)的二进制格式,并且很好本网站(https://mothereff.in/utf-8)在utf8中解码
意思是:“·” @en
但是在python 3.7.3中,我遇到了一个众所周知的错误:UnicodeDecodeError: 'utf-8' codec can't decode byte 0xed in position 3: invalid continuation byte尝试mystring.decode('utf8')
如果我尝试做相反的事情: '"· "@en'.encode('utf8)我得到以下表示形式:b'"\xf0\x90\x91\x96\xf0\x90\x91\xb1\xf0\x90\x91\x9d\xf0\x90\x91\xbe\xf0\x90\x91\xaf \xf0\x90\x91\xa8\xf0\x90\x91\xa4\xf0\x90\x91\x93\xf0\x90\x91\xa9\xf0\x90\x91\x9a\xf0\x90\x91\xa7\xf0\x90\x91\x91"@en'它不是完全相同的字符串,但是随后repr.decode('utf8')正确地解码为相同的东西。
有人可以帮助我了解为什么解码第一个字节字符串不起作用吗?我知道由于错误,第一个字节字符串不是有效的UTF-8字符串。但是,为什么我所链接的网站对它的解码效果很好,而python无法做到?先感谢您!
最终编辑 接受答案后,我对此进行了一些额外的研究,发现该字符串是使用CESU-8编解码器编码的。今天显然已经弃用了。但是有些人仍在使用它...因此,我找到了一个可以写utf-8编解码器变体的程序包,它可以解码此字符串。我认为这将帮助很多与我有相同问题的人。Python库:https://github.com/LuminosoInsight/python-ftfy 添加的编解码器为'utf-8-variants'。我希望这会帮助比我有同样需求的人们。
似乎Python不想接受某些字节序列作为有效的UTF-8,而某些网站(https://mothereff.in/utf-8)接受它。其中之一一定是错的,对吗?让我们来看看。
b'\xc2\xb7'Python接受前两个字节()。Python不喜欢的第一件事是::\xed\xa0\x81\xed\xb1\x96,在该网站上被解释为。
让我们\xed\xa0\x81\xed\xb1\x96以二进制格式查看:
11101101
10100000
10000001
11101101
10110001
10010110
Run Code Online (Sandbox Code Playgroud)
RFC3629表示UTF-8解释为:
Run Code Online (Sandbox Code Playgroud)Char. number range | UTF-8 octet sequence (hexadecimal) | (binary) --------------------+--------------------------------------------- 0000 0000-0000 007F | 0xxxxxxx 0000 0080-0000 07FF | 110xxxxx 10xxxxxx 0000 0800-0000 FFFF | 1110xxxx 10xxxxxx 10xxxxxx 0001 0000-0010 FFFF | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
因此,有两个三个字节的字符:
1110 1101 10 100000 10 000001?1101100000000001或D801
1110 1101 10 110001 10 010110?1101110001010110或DC56
您可以在此处查看如何合并代理:
代理对表示代码点0x10000 +(H?0xD800)×0x400 +(L?0xDC00),其中H和L分别是高和低代理的数值。
如果将它们结合起来,将得到:
0x10000 +(0xD801-0xD800)* 0x400 +(0xDC56-0xDC00)= 0x10456
但是,高低替代项是为不适合16位的字符的UTF-16表示而设计的,这就是unicode.org所说的在UTF-8中使用这样的替代对:
问:如何将UTF-16代理对转换为
<D800 DC00>UTF-8?作为一个4字节序列还是两个单独的3字节序列?答:UTF-8的定义要求将补充字符(在UTF-16中使用代理对的补充字符)用单个4字节序列编码。但是,在较老的软件中,尤其是在引入UTF-16之前或在特定限制下与UTF-16环境互操作的软件,通常会生成3字节序列对。这样的编码不符合所定义的UTF-8。有关此类非UTF-8数据格式的正式说明,请参见UTR#26:UTF-16的兼容性编码方案:8位(CESU)。使用CESU-8时,由于格式的相似性,必须格外小心,不要意外地将数据视为UTF-8。[AF]
这里的关键点是“这种编码不符合所定义的UTF-8”。因此,您的输入实际上是无效的UTF-8序列,Python拒绝了它。
要回答这个问题: