问题:
我尝试了什么:
我开始使用chardet,但应用程序受到了重大的性能影响,因为它在检测到编码之前将整个文件加载到RAM中。然后我想也许我应该将一些有代表性的数据读入chardet的检测方法,但后来意识到我没有办法不丢失任何可能导致问题的随机字符(例如'®'字符会导致文本文件出现问题否则将解码为UTF-8就好了)。除非必要,否则为了避免受到这种打击,我走了这条路:
def get_file_handle(self):
"""
Default encoding is UTF-8. If that fails, try Western European (Windows-1252), else use chardet to detect
:return: file handle (f)
"""
try:
with codecs.open(self.current_file, mode='rb', encoding='utf-8') as f:
return f
except UnicodeDecodeError:
try:
with codecs.open(self.current_file, mode='rb', encoding='cp1252') as f:
return f
except UnicodeDecodeError:
# read raw data and detect encoding via chardet (last resort)
raw_data = open(self.current_file, 'r').read()
result = chardet.detect(raw_data)
char_enc = result['encoding']
with codecs.open(self.current_file, mode='rb', encoding=char_enc) as f:
return f
虽然这有效,但在极少数情况下它会到达第三个/最里面的异常,它仍然将整个文件读入RAM。简单地阅读一些随机代表性数据可能会错过文本文档中的违规字符。这就是我想做的事情:
当我得到UnicodeDecodeError时,回溯的最后一行是:
UnicodeDecodeError: 'utf8' codec can't decode byte 0xae in position 2867043: invalid start byte
我想获取字节偏移量(0xae
),然后从文件前后抓取1.000个字符以提供给chardet进行检测,从而包括违规字符和附加数据到基数编码预测。
我已经知道如何以块的形式读取数据(但也可以随意添加),主要是我对如何从回溯中获取字节偏移感兴趣。
答案 0 :(得分:1)
这个怎么样:
except UnicodeDecodeError as e:
# read raw data and detect encoding via chardet (last resort)
with open(self.current_file, 'r') as f:
f.seek(e.start - 1000)
raw_data = f.read(2000)
result = chardet.detect(raw_data)
...