【问题标题】:Why does csv.reader fail when the file size is larger than 40K bytes?当文件大小大于 40K 字节时,为什么 csv.reader 会失败?
【发布时间】:2018-11-03 01:29:08
【问题描述】:

我有以下代码:

with open(filename, 'rt') as csvfile:
    csvDictReader = csv.DictReader(csvfile, delimiter=',', quotechar='"')
    for row in csvDictReader:
        print(row)

只要文件大小小于 40k 字节,程序就会运行良好。 当文件大小超过 40k 时,我在尝试读取文件时收到此错误:

UnicodeDecodeError: 'utf-8' codec can't decode byte 0xa0 in position 7206: invalid start byte

实际文件内容似乎没有问题,只有文件本身的大小(40k 字节真的很小)。

当文件大小大于 40K 字节时,错误总是发生在包含第 32K 字节的行上。

我有一种感觉,python 无法毫无例外地读取超过 40K 字节的文件,而只是在中间的第 32K 字节附近截断它。那是对的吗?这个限制在哪里定义?

【问题讨论】:

  • 文件内容,而不是文件大小。您在位置 7206 中有一个非 Unicode 字节。
  • 不,Python 没有这个限制。
  • 你用的是python 2还是3?您是否希望文件中包含任何非 Ascii 字符?你知道它是怎么编码的吗?最明显的是,您是否打开了编辑器并检查了字符位置 7206 处的内容?你可以print(open(filename, 'rb').read(7240)[7190:])看看那个区域的人物。
  • @tdelaney:它试图解码的事实表明它是 Python 3; Python 2 的 open 不解码,Python 2 的 csv 模块即使处理了 unicode 类型也不处理(from io import open 在 Py2 中会得到 Py3 风格的 open,但它不会兼容csv,它只处理Py2中的str类型)。

标签: python file csv reader


【解决方案1】:

您的文件中有无效的 UTF-8 数据。这与csv 模块无关,也与文件大小无关;您的较大文件中包含无效数据,较小的文件中没有。简单地做:

 with open(filename) as f:
     f.read()

应该会触发同样的错误,这纯粹是遇到了无效的 UTF-8 字节,这表明您的文件不是以 UTF-8 开头,或者已经以某种方式损坏。

如果您的文件实际上是不同的编码(例如latin-1cp1252 等;file 命令行实用程序可能有助于识别,但对于许多 ASCII 超集编码,您只需 知道),将其作为encoding 参数传递给open 以代替默认的语言环境(在这种情况下为utf-8),因此您可以正确解码字节,例如:

    # Also add newline='' to defer newline processing to csv module, where it's part
    # of the CSV dialect
    with open(filename, encoding='latin-1', newline='') as csvfile:
        csvDictReader = csv.DictReader(csvfile, delimiter=',', quotechar='"')
        for row in csvDictReader:
            print(row)

【讨论】:

  • 为了记录,在latin-1cp1252中,\xa0是不间断空格的编码(相当于HTML转义 )。您不会在常规文本编辑器或电子表格查看器中看到它(与纯空格没有任何区别),但十六进制编辑器应该使它像一天一样简单。
  • f.read() 技巧很有帮助,倒数第三行有一个隐藏字符,这是第 40K 个字节的行(所以当我删除该行时然后我认为通过减少到 40k 以下可以解决问题)
【解决方案2】:

文件大小不是真正的问题 查看异常:

UnicodeDecodeError: 'utf-8' codec can't decode byte 0xa0 in position 7206: invalid start byte

你应该首先处理编码问题

with open(filename, 'rt', encoding='utf-8', errors='ignore') as csvfile:

这将忽略编码错误

【讨论】:

  • 假设 csv 是 utf-8 编码的。这可能是读取的默认值,但并不意味着它对文件是正确的。
  • errors="ignore" 仅当您的文件已知为 UTF-8,但在某些方面已损坏时,才是正确的解决方案。对于其他一切,这意味着“我不在乎正确性,并且很乐意到处丢失数据。”找出正确的编码并使用它,不要只是说“UTF-8 是唯一可能的编码,所以它必须是可忽略的损坏。”奇怪的是,它是完全有效的cp1252,由一些被告知使用区域设置编码而不是 UTF-16(Windows 的常见可移植编码)或 UTF-8(其他任何地方的可移植编码)的 Windows 程序生成。
猜你喜欢
  • 2017-06-01
  • 1970-01-01
  • 2010-10-01
  • 1970-01-01
  • 2016-01-26
  • 2021-10-29
  • 2021-12-31
  • 2010-12-08
  • 2020-11-13
相关资源
最近更新 更多