我正在尝试打开一个这样的文件:
with open("myfile.txt", encoding="utf-8") as f:但是myfile.txt来自我的应用程序的用户。在90%的情况下,这个文件是以非UTF-8格式出现的,这会导致应用程序退出,因为它无法正确读取它。该错误类似于'utf-8' codec can't decode byte 0x9c
我用谷歌搜索了一下,发现一些Stackoverflow的答案是这样打开我的文件的:
with open("myfile.txt", encoding="utf-8", errors="surrogateescape") as f:但其他答案据说是这样使用的:
with open("myfile.txt", encoding="utf-8", errors="replace") as f:那么errors="replace"和errors="surrogateescape"之间的区别是什么,哪一个可以修复文件中的非UTF8字节呢?
发布于 2019-06-04 18:02:51
医生说:
' Replace ':替换为合适的替换标记;Python将在解码时对内置编解码器使用官方的U+FFFD替换字符,以及‘?’在编码上。在replace_errors()中实现。
..。
‘surrogate replace’:解码时,将字节替换为从U+DC80到U+DCFF的各个代理代码。在对数据进行编码时,当使用'surrogateescape‘错误处理程序时,此代码将被转换回相同的字节。(有关更多信息,请参阅PEP 383。)
这意味着在replace中,任何有问题的字节都将被替换为相同的U+FFFD替换字符,而在surrogateescape中,每个字节将被替换为不同的值。例如,'\xe9'将替换为'\udce9','\xe8'将替换为'\udce8'。
因此,使用replace,您可以获得有效的unicode字符,但会丢失文件的原始内容;而使用replace,您可以知道原始字节(甚至可以使用.encode(errors='surrogateescape')准确地重建它),但是您的unicode字符串是不正确的,因为它包含原始的代理代码。
长话短说:如果原始的违规字节无关紧要,并且您只想摆脱错误,那么replace是一个很好的选择,如果您需要保留它们以供以后处理,那么surrogateescape是一个不错的选择。
当你有一个主要包含ascii字符和一些(重音的)非ascii字符的文件时,surrogateescape有一个非常好的特性。还有一些用户偶尔会使用非UTF8编辑器修改文件(或者没有声明UTF8编码)。在这种情况下,您最终得到的文件主要包含utf8数据和一些采用不同编码的字节,对于使用非英语、西欧语言(如法语、西班牙语的葡萄牙语)的windows用户来说,通常是CP1252。在这种情况下,可以构建一个转换表,将代理字符映射到cp1252字符集中的等效字符:
# first map all surrogates in the range 0xdc80-0xdcff to codes 0x80-0xff
tab0 = str.maketrans(''.join(range(0xdc80, 0xdd00)),
''.join(range(0x80, 0x100)))
# then decode all bytes in the range 0x80-0xff as cp1252, and map the undecoded ones
# to latin1 (using previous transtable)
t = bytes(range(0x80, 0x100)).decode('cp1252', errors='surrogateescape').translate(tab0)
# finally use above string to build a transtable mapping surrogates in the range 0xdc80-0xdcff
# to their cp1252 equivalent, or latin1 if byte has no value in cp1252 charset
tab = str.maketrans(''.join(chr(i) for i in range(0xdc80, 0xdd00)), t)然后,您可以解码包含utf8和cp1252组合的文件:
with open("myfile.txt", encoding="utf-8", errors="surrogateescape") as f:
for line in f: # ok utf8 has been decoded here
line = line.translate(tab) # and cp1252 bytes are recovered here我已经成功地使用该方法多次恢复csv文件,这些文件是以utf8格式生成的,并已在Windows机器上使用Excel进行了编辑。
同样的方法也可以用于从ascii派生的其他字符集。
发布于 2019-06-04 18:49:31
我的问题是,该文件包含具有混合编码类型的行。
修复方法是删除encoding="utf-8"并添加errors="replace"。所以最后的open()代码行应该是这样的:
with open("myfile.txt", errors="replace") as f:如果可以检测文件的编码类型,我会将其添加为encoding参数,但不幸的是无法检测到它。
https://stackoverflow.com/questions/56441390
复制相似问题