Python CSV错误:行包含NULL字节


102

我正在使用以下代码处理一些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

我能做什么?Google似乎建议它可能是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')

这是我得到的输出:

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

因此,该文件确实包含NUL字节。


什么是od -c说像第一线的外观?
伊格纳西奥·巴斯克斯

我应该运行什么查询,例如cat my.csv | od -c | 更多 ?我得到的是:0000000 D部F amil
AP257 2010年

CSV是如何生成的?通过excel,您可以尝试方言。否则看说:stackoverflow.com/questions/2753022/...
博士jimbob

谢谢。这不是我的CSV,很遗憾,我没有更改它的能力。我认为它已创建为Excel,并另存为CSV(boo)。方言听起来不错,我会尽力!
AP257

如果它实际上已另存为CSV,则应该可以使用。我有时发现的一件事是伪装成CSV的TSV(制表符分隔)文件,因此您可以尝试将定界符设置为'\ t'。如果将其另存为Excel文件,并且扩展名更改为CSV,则任何方言都无法使用。我认为在这种情况下,您唯一的选择是使用Excel将副本另存为适当的CSV。
Thomas K

Answers:


104

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

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

顺便说一句,您是否使用文本编辑器查看了文件(包括最后几行)?它实际上看起来像其他文件(没有“ NULL字节”例外)一样的合理CSV文件吗?


非常感谢您提供的非常详细的帮助。文件中有很多\ x00字符(请参阅问题编辑)-很奇怪,因为在文本编辑器中,它看起来像是一个非常合理的CSV文件。
AP257

1
@ AP257:'\xd0\xcf\x11\xe0\xa1\xb1\x1a\xe1是表示OLE2复合文档文件的“签名”,例如Excel 97-2003 .XLS文件。我发现“在文本编辑器中,它看起来像是一个完全合理的CSV文件”,这简直令人难以置信。您必须一直在另一个文件夹或另一台机器上或其他时间查看其他文件,有效的CSV文件。请注意,您的od输出不是来自XLS文件。
约翰·马钦

8
@ AP257:您没有接受此答案的任何特定原因?
约翰·马钦

可行,但应该可行,并且可以通过过滤CSV的类似文件的对象即时进行传递,并且可以直接传递给它csv.reader
Gerrit

1
fo.write(data.replace('\x00', ''))应该fo.write(data.replace(b'\x00', b''))吗?Python 3.6在这里...
Boern

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

这对我有用。


对于我的情况,null为'\ 0'值。谢谢。
Joab Mendes

19

将其读取为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文件的目录。


13

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

我认为这可能对您有帮助。


7
感谢您指出该模块。有趣的是,我去下载了它,发现作者就是@John_Machin,他也是这个问题的最高评论。
伊万(Evan)2012年

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)

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))

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”标志打开它。


@ AP257:“没有帮助”吗?意味着什么?任何特定的错误消息?
S.Lott

1
@ S.Lott:表示他得到的答案与以前相同。现实情况是,他正在处理变色龙或shapeshifter文件...当他将其与od文本编辑器一起转储或在文本编辑器中查看时,它看起来像一个完全正常的CSV文件。但是,当他使用Python repr()转储前几个字节时,它就像一个Excel .XLS文件(已重命名为CSV扩展名)。
约翰·马钦

@约翰梅钦:“一个Excel .xls文件(一个已经更名为有一个CSV延伸”是有道理的,它不能在所有被处理。
美国洛特

1
@ S.Lott:有了这些内容,csv模块就无法处理它;但是xlrd模块可以处理它。明智地,如果输入确实是带有名称的文件,则这两个模块都不从输入文件的名称推断任何内容。
约翰·马钦

1
@John Machin:“这两个模块都不会从输入文件的名称中推断出任何东西”。真正。我的应用程序框架取决于这一事实。我们不相信文件名意味着任何东西,因为人们会犯错误(“谎言”)。因此,我们必须检查一堆替代方案,直到单击一次。
S.Lott


2

代替csv阅读器,我对字符串使用read文件和split函数:

lines = open(input_file,'rb') 

for line_all in lines:

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

1

我遇到了同样的错误。将文件保存在UTF-8中,可以正常工作。


1
您可能会收到相同的错误消息,但原因可能有所不同-您可能最初将其保存为UTF-16(记事本称为“ Unicode”)。
约翰·马钦

1

当我使用OpenOffice Calc创建CSV文件时,这发生在我身上。当我在文本编辑器中创建CSV文件时,即使以后使用Calc编辑它,也没有发生。

通过将文本从Calc创建的文件复制粘贴到新的编辑器创建的文件中,我解决了我的问题。


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...

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


0

对于所有那些讨厌的“ rU”文件模式的人:我只是尝试从Mac上的Windows计算机上使用“ rb”文件模式打开CSV文件,而我从csv模块中得到了此错误:

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

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


0

我在使用scrapy并获取压缩的csvfile时遇到此问题,而没有正确的中间件将响应主体解压缩,然后再将其交给csvreader。因此,该文件不是真正的csv文件,因此引发了line contains NULL byte错误。


0

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

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

我试图打开一个已压缩但扩展名为“ .csv”而不是“ csv.gz”的文件。在我使用gzip.open之前,此错误一直显示


-1

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

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

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

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.