Python CSV错误:行包含NULL字节

时间:2010-11-12 15:18:55

标签: 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))

一个文件抛出了这个错误:

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

我该怎么办?谷歌似乎暗示它可能是一个Excel文件被不正当地保存为.csv。有什么方法可以解决这个问题吗?

== UPDATE ==

按照下面@ 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字节。

15 个答案:

答案 0 :(得分:96)

正如@ 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的位置(如果有) / p>

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(或\0输出中的od -c),那么你肯定在文件中有NUL字节,你需要做这样的事情:

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

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

答案 1 :(得分:17)

将它读作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文件的目录。

答案 2 :(得分:16)

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

这适合我。

答案 3 :(得分:12)

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

我认为这对你有所帮助。

答案 4 :(得分:10)

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

How to convert a file to utf-8 in Python?

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)

答案 5 :(得分: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))

答案 6 :(得分:2)

你为什么这样做?

 reader = csv.reader(open(filepath, "rU"))

文档很清楚你必须这样做:

with open(filepath, "rb") as src:
    reader= csv.reader( src )

模式必须为“rb”才能阅读。

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

  

如果csvfile是一个文件对象,则必须在平台上打开“b”标志,这会产生影响。

答案 7 :(得分:2)

显然它是一个XLS文件而不是CSV文件http://www.garykessler.net/library/file_sigs.html确认

答案 8 :(得分:2)

我使用read文件和split函数代替csv reader而不是字符串:

lines = open(input_file,'rb') 

for line_all in lines:

    line=line_all.replace('\x00', '').split(";")

答案 9 :(得分:1)

我得到了同样的错误。将文件保存为UTF-8并且有效。

答案 10 :(得分:1)

我在打开从Web服务生成的CSV时遇到了同样的问题,该服务在空标题中插入了NULL字节。我做了以下清理文件:

with codecs.open ('my.csv', 'rb', 'utf-8') as myfile:
    data = myfile.read()
    # clean file first if dirty
    if data.count( '\x00' ):
        print 'Cleaning...'
        with codecs.open('my.csv.tmp', 'w', 'utf-8') as of:
            for line in data:
                of.write(line.replace('\x00', ''))

        shutil.move( 'my.csv.tmp', 'my.csv' )

with codecs.open ('my.csv', 'rb', 'utf-8') as myfile:
    myreader = csv.reader(myfile, delimiter=',')
    # Continue with your business logic here...

声明: 请注意,这会覆盖原始数据。确保您有备份副本。你被警告了!

答案 11 :(得分:0)

对于所有那些'rU'文件模式的仇恨:我只是尝试使用'rb'文件模式从Mac上的Windows机器打开CSV文件,我从csv模块得到了这个错误:

Error: new-line character seen in unquoted field - do you need to 
open the file in universal-newline mode?

以'rU'模式打开文件可以正常工作。我喜欢通用换行模式 - 它为我节省了很多麻烦。

答案 12 :(得分:0)

我在使用scrapy并获取压缩的csvfile而没有正确的中间件解压响应主体然后将其交给csvreader时遇到了这个问题。因此,该文件实际上不是一个csv文件,并相应地抛出了line contains NULL byte错误。

答案 13 :(得分:0)

您是否尝试过使用gzip.open?

with gzip.open('my.csv', 'rb') as data_file:

我试图打开一个已压缩但扩展名为“ .csv”而不是“ csv.gz”的文件。在我使用gzip.open

之前,该错误一直显示

答案 14 :(得分:-1)

一种情况是 - 如果CSV文件包含空行,则可能会显示此错误。在我们继续写或读之前,检查行是否必要。

for row in csvreader:
        if (row):       
            do something

我通过在代码中添加此检查来解决我的问题。