Python CSV 错误:行包含 NULL 字节

123 投票
19 回答
188591 浏览
提问于 2025-04-16 06:59

我正在处理一些CSV文件,使用的代码如下:

reader = csv.reader(open(filepath, "rU"))
try:
    for row in reader:
        print 'Row read successfully!', row
except csv.Error, e:
    sys.exit('file %s, line %d: %s' % (filename, reader.line_num, e))

但是有一个文件出现了这个错误:

file my.csv, line 1: line contains NULL byte

我该怎么办呢?谷歌似乎建议这可能是一个不正确保存为.csv格式的Excel文件。我能用Python解决这个问题吗?

== 更新 ==

根据@JohnMachin的建议,我在我的脚本中添加了这些代码:

print repr(open(filepath, 'rb').read(200)) # dump 1st 200 bytes of file
data = open(filepath, 'rb').read()
print data.find('\x00')
print data.count('\x00')

然后我得到了这个输出:

'\xd0\xcf\x11\xe0\xa1\xb1\x1a\xe1\x00\x00\x00\x00\x00\x00\x00\x00\ .... <snip>
8
13834

所以这个文件确实包含了NUL字节。

19 个回答

22

把它当作UTF-16格式读取也是我遇到的问题。

这是我最后成功运行的代码:

f=codecs.open(location,"rb","utf-16")
csvread=csv.reader(f,delimiter='\t')
csvread.next()
for row in csvread:
    print row

这里的location是你csv文件所在的文件夹。

30
data_initial = open("staff.csv", "rb")
data = csv.reader((line.replace('\0','') for line in data_initial), delimiter=",")

这对我有效。

121

正如 @S.Lott 所说,你应该以 'rb' 模式打开文件,而不是 'rU' 模式。不过,这可能并不是你目前问题的根源。根据我的了解,如果数据中有嵌入的 \r,使用 'rU' 模式可能会让你遇到麻烦,但不会引发其他问题。我还注意到你有几个文件(都是用 'rU' 打开的??),但只有一个文件出现了问题。

如果 csv 模块提示你的文件中有一个 "NULL" 字节(这个提示有点傻,应该是 "NUL"),那么你需要检查一下你的文件内容。我建议你即使使用 'rb' 模式后问题消失,也要检查一下文件。

repr() 是你调试时的好帮手。它会清楚地显示你文件中的内容,而且不受平台影响(这对那些不知道 od 是什么的人很有帮助)。你可以这样做:

print repr(open('my.csv', 'rb').read(200)) # dump 1st 200 bytes of file

然后仔细复制粘贴(不要重新输入)结果到你问题的编辑中(而不是评论里)。

另外,如果文件真的有问题,比如在文件开头附近没有 \r 或 \n,reader.line_num 报告的行号将会是(不太有用的)1。你可以通过以下方式找到第一个 \x00 的位置(如果有的话):

data = open('my.csv', 'rb').read()
print data.find('\x00')

确保你用 repr 或 od 至少输出这么多字节。

data.count('\x00') 这个命令告诉你什么?如果有很多,你可能想要做一些类似的操作:

for i, c in enumerate(data):
    if c == '\x00':
        print i, repr(data[i-30:i]) + ' *NUL* ' + repr(data[i+1:i+31])

这样你就可以看到 NUL 字节的上下文。

如果你在输出中看到 \x00(或者在你的 od -c 输出中看到 \0),那么文件中肯定有 NUL 字节,你需要做一些类似这样的处理:

fi = open('my.csv', 'rb')
data = fi.read()
fi.close()
fo = open('mynew.csv', 'wb')
fo.write(data.replace('\x00', ''))
fo.close()

顺便问一下,你有没有用文本编辑器查看文件(包括最后几行)?它看起来真的像其他没有 "NULL byte" 异常的合理 CSV 文件吗?

撰写回答