从Python UnicodeDecodeError异常中获取错误的字节偏移量

时间:2015-10-13 19:30:59

标签: python utf-8 character-encoding

问题:

  • 我有大量(> 2GB)包含感兴趣数据的文本文件
  • 在> 90%的情况下,我可以假设此数据格式为UTF-8或西欧
  • 在极少数情况下,我有其他奇怪的编码

我尝试了什么:

我开始使用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进行检测,从而包括违规字符和附加数据到基数编码预测。

我已经知道如何以块的形式读取数据(但也可以随意添加),主要是我对如何从回溯中获取字节偏移感兴趣。

1 个答案:

答案 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)
        ...