我必须将一个文本文件读入Python。文件编码为:
file -bi test.csv
text/plain; charset=us-ascii
这是一个第三方文件,我每天都会得到一个新的文件,所以我宁愿不更改它。该文件包含非ascii字符,例如。我需要使用python来读取行,并且我可以忽略包含非ascii字符的行。
我的问题是,当我在Python中读取文件时,当到达存在非ascii字符的行时会得到UnicodeDecodeError,并且我无法读取文件的其余部分。
有没有办法避免这种情况。如果我尝试这样做:
fileHandle = codecs.open("test.csv", encoding='utf-8');
try:
for line in companiesFile:
print(line, end="");
except UnicodeDecodeError:
pass;
然后,当遇到错误时,for循环结束,我无法读取文件的其余部分。我想跳过导致错误的那一行,然后继续。如果可能的话,我宁愿不对输入文件做任何更改。
有没有办法做到这一点?非常感谢。
发布于 2014-07-08 02:14:12
您的文件似乎没有使用UTF-8编码。在打开文件时,使用正确的编解码器非常重要。
您可以使用errors
关键字告诉open()
如何处理解码错误:
错误是一个可选字符串,它指定如何处理编码和解码错误-这不能在二进制模式下使用。有多种标准错误处理程序可用,但任何已注册到
codecs.register_error()
的错误处理程序名称也是有效的。标准名称为:
如果存在编码错误,则使用
'strict'
引发ValueError
异常。None
的默认值具有相同的effect.'ignore'
忽略错误。请注意,忽略编码错误可能会导致数据loss.'replace'
导致替换标记(如'?')在存在格式错误的data.'surrogateescape'
的地方插入,将把任何不正确的字节表示为从U+DC80到U+DCFF的Unicode专用区域中的代码点。然后,当在写入数据时使用surrogateescape
错误处理程序时,这些私有代码点将被转换回相同的字节。这对于处理未知encoding.'xmlcharrefreplace'
中的文件很有用,只有在写入文件时才支持。编码不支持的字符将替换为相应的XML字符引用&#nnn;
.'backslashreplace'
(仅在书写时支持)将不支持的字符替换为Python的带反斜杠的转义序列。使用'strict'
以外的任何命令('ignore'
、'replace'
等)打开文件然后将允许您读取该文件,而不会引发异常。
请注意,解码是按缓冲的数据块进行的,而不是按文本行进行的。如果必须逐行检测错误,请使用surrogateescape
处理程序并测试每行读取的代理范围中的代码点:
import re
_surrogates = re.compile(r"[\uDC80-\uDCFF]")
def detect_decoding_errors_line(l, _s=_surrogates.finditer):
"""Return decoding errors in a line of text
Works with text lines decoded with the surrogateescape
error handler.
Returns a list of (pos, byte) tuples
"""
# DC80 - DCFF encode bad bytes 80-FF
return [(m.start(), bytes([ord(m.group()) - 0xDC00]))
for m in _s(l)]
例如。
with open("test.csv", encoding="utf8", errors="surrogateescape") as f:
for i, line in enumerate(f, 1):
errors = detect_decoding_errors_line(line)
if errors:
print(f"Found errors on line {i}:")
for (col, b) in errors:
print(f" {col + 1:2d}: {b[0]:02x}")
考虑到并不是所有的解码错误都可以从容恢复。虽然UTF-8被设计为在遇到小错误时具有健壮性,但其他多字节编码,如UTF-16和UTF-32,无法处理丢弃或额外的字节,这将影响行分隔符的精确定位。然后,上述方法会导致文件的其余部分被视为一个长行。如果文件足够大,那么在‘行’足够大的情况下,就会导致MemoryError
异常。
https://stackoverflow.com/questions/24616678
复制相似问题