Python CSV错误:行包含NULL字节

AP2*_*257 92 python csv

我正在使用一些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))
Run Code Online (Sandbox Code Playgroud)

一个文件抛出此错误:

file my.csv, line 1: line contains NULL byte
Run Code Online (Sandbox Code Playgroud)

我能做什么?谷歌似乎暗示它可能是一个Excel文件被不正当地保存为.csv.有什么方法可以解决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')
Run Code Online (Sandbox Code Playgroud)

这是我得到的输出:

'\xd0\xcf\x11\xe0\xa1\xb1\x1a\xe1\x00\x00\x00\x00\x00\x00\x00\x00\ .... <snip>
8
13834
Run Code Online (Sandbox Code Playgroud)

所以该文件确实包含NUL字节.

Joh*_*hin 100

正如@ 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
Run Code Online (Sandbox Code Playgroud)

并仔细复制/粘贴(不要重新输入)结果到您的问题的编辑(而不是评论).

另请注意,如果文件真的很狡猾,例如没有\ r或\n在距文件开头合理的距离内,报告的行号reader.line_num将是(无用的)1.\x00通过执行查找第一个(如果有)的位置

data = open('my.csv', 'rb').read()
print data.find('\x00')
Run Code Online (Sandbox Code Playgroud)

并确保使用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])
Run Code Online (Sandbox Code Playgroud)

这样你就可以在上下文中看到NUL字节.

如果您可以\x00在输出中(或\0od -c输出中)看到,那么您肯定在文件中有NUL字节,并且您需要执行以下操作:

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

顺便问一下,你是否用文本编辑器查看了文件(包括最后几行)?它实际上看起来像一个合理的CSV文件,像另一个(没有"NULL字节"异常)文件?

  • @ AP257:你有没有接受这个答案的特殊原因? (8认同)
  • 不应该`fo.write(data.replace('\x00', ''))` 是`fo.write(data.replace(b'\x00', b''))`吗?Python 3.6 在这里... (2认同)

Use*_*ser 19

读它作为UTF-16也是我的问题.

这是我的代码,最终工作:

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

其中location是csv文件的目录.


小智 18

data_initial = open("staff.csv", "rb")
data = csv.reader((line.replace('\0','') for line in data_initial), delimiter=",")
Run Code Online (Sandbox Code Playgroud)

这适合我.


aya*_*yaz 13

我也碰到了这个问题.使用Python csv模块,我试图读取在MS Excel中创建的XLS文件NULL byte并遇到您遇到的错误.我环顾四周,找到了xlrd Python模块,用于从MS Excel电子表格文件中读取和格式化数据.使用该xlrd模块,我不仅能够正确读取文件,而且还可以以前所未有的方式访问文件的许多不同部分.

我认为它可能对你有帮助.

  • 谢谢你指出那个模块.有趣的是,我去下载它并注意到作者是@John_Machin,他也是这个问题的最高评论. (7认同)

小智 11

将源文件的编码从UTF-16转换为UTF-8解决了我的问题.

如何在Python中将文件转换为utf-8?

import codecs
BLOCKSIZE = 1048576 # or some other, desired size in bytes
with codecs.open(sourceFileName, "r", "utf-16") as sourceFile:
    with codecs.open(targetFileName, "w", "utf-8") as targetFile:
        while True:
            contents = sourceFile.read(BLOCKSIZE)
            if not contents:
                break
            targetFile.write(contents)
Run Code Online (Sandbox Code Playgroud)


woo*_*oot 7

如果要假装它们不存在,您可以内联生成器来过滤掉空值.当然这是假设空字节实际上不是编码的一部分,实际上是某种错误的工件或错误.

with open(filepath, "rb") as f:
    reader = csv.reader( (line.replace('\0','') for line in f) )

    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))
Run Code Online (Sandbox Code Playgroud)


S.L*_*ott 2

你为什么做这个?

\n\n
 reader = csv.reader(open(filepath, "rU"))\n
Run Code Online (Sandbox Code Playgroud)\n\n

文档非常清楚你必须这样做:

\n\n
with open(filepath, "rb") as src:\n    reader= csv.reader( src )\n
Run Code Online (Sandbox Code Playgroud)\n\n

模式必须是“rb”才能读取。

\n\n

http://docs.python.org/library/csv.html#csv.reader

\n\n
\n

如果 csvfile 是文件对象,则必须在有影响的平台上使用 \xe2\x80\x98b\xe2\x80\x99 标志打开它。

\n
\n