首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >errors=surrogateescape vs errors=replace

errors=surrogateescape vs errors=replace
EN

Stack Overflow用户
提问于 2019-06-04 17:45:02
回答 2查看 2.1K关注 0票数 1

我正在尝试打开一个这样的文件:

代码语言:javascript
复制
with open("myfile.txt", encoding="utf-8") as f:

但是myfile.txt来自我的应用程序的用户。在90%的情况下,这个文件是以非UTF-8格式出现的,这会导致应用程序退出,因为它无法正确读取它。该错误类似于'utf-8' codec can't decode byte 0x9c

我用谷歌搜索了一下,发现一些Stackoverflow的答案是这样打开我的文件的:

代码语言:javascript
复制
with open("myfile.txt", encoding="utf-8", errors="surrogateescape") as f:

但其他答案据说是这样使用的:

代码语言:javascript
复制
with open("myfile.txt", encoding="utf-8", errors="replace") as f:

那么errors="replace"errors="surrogateescape"之间的区别是什么,哪一个可以修复文件中的非UTF8字节呢?

EN

回答 2

Stack Overflow用户

发布于 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字符集中的等效字符:

代码语言:javascript
复制
# 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组合的文件:

代码语言:javascript
复制
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派生的其他字符集。

票数 4
EN

Stack Overflow用户

发布于 2019-06-04 18:49:31

我的问题是,该文件包含具有混合编码类型的行。

修复方法是删除encoding="utf-8"并添加errors="replace"。所以最后的open()代码行应该是这样的:

代码语言:javascript
复制
with open("myfile.txt", errors="replace") as f:

如果可以检测文件的编码类型,我会将其添加为encoding参数,但不幸的是无法检测到它。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/56441390

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档