Python CSV 错误:行包含 NULL 字节
Posted
技术标签:
【中文标题】Python CSV 错误:行包含 NULL 字节【英文标题】:Python CSV error: line contains NULL byte 【发布时间】:2011-05-09 03:22:45 【问题描述】:我正在处理一些 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 字节。
【问题讨论】:
od -c
说第一行是什么样的?
我应该运行什么查询,比如 cat my.csv | od -c |更多的 ?我得到:0000000 D e p a r t m e n t F a m i l
CSV 是如何生成的?从 excel 中,您也许可以尝试一种方言。不然看说:***.com/questions/2753022/…
谢谢。这不是我的 CSV,不幸的是我没有能力改变它。我认为它已创建为 Excel 并保存为 CSV (boo)。方言听起来是个好主意 - 我会试试看!
如果它实际上被保存为 CSV,它应该可以工作。我有时会发现一件事是伪装成 CSV 的 TSV(制表符分隔)文件,因此您可以尝试设置分隔符 '\t'。如果它被保存为 Excel 文件,并且扩展名更改为 CSV,则没有方言可以工作。我认为在这种情况下您唯一的选择是使用 Excel 将副本保存为正确的 CSV。
【参考方案1】:
正如@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 字节”例外)文件一样合理的 CSV 文件吗?
【讨论】:
非常感谢您提供如此详细的帮助。文件中有很多 \x00 字符(请参阅问题的编辑) - 这很奇怪,因为在文本编辑器中它看起来像一个完全合理的 CSV 文件。 @AP257:'\xd0\xcf\x11\xe0\xa1\xb1\x1a\xe1
是表示 OLE2 复合文档文件的“签名”——例如Excel 97-2003 .XLS 文件。我发现“在文本编辑器中它看起来像一个完全合理的 CSV 文件”是完全难以置信。您一定在另一个文件夹或另一台机器上或在其他时间查看过不同的文件、有效的 CSV 文件。请注意,您的 od
输出不是来自 XLS 文件。
有效,但应该可以使用类似文件的对象来过滤 CSV 并且可以直接传递给 csv.reader
。
我认为od
在这个答案中是os
的错字。
不应该 fo.write(data.replace('\x00', ''))
是 fo.write(data.replace(b'\x00', b''))
吗? Python 3.6 在这里...【参考方案2】:
data_initial = open("staff.csv", "rb")
data = csv.reader((line.replace('\0','') for line in data_initial), delimiter=",")
这对我有用。
【讨论】:
解决了我的情况,null 是 '\0' 值。谢谢。【参考方案3】:将其读取为 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 文件的目录。
【讨论】:
【参考方案4】:如果你想假装它们不存在,你可以只内联一个生成器来过滤掉空值。当然,这是假设空字节并不是真正的编码的一部分,并且确实是某种错误的工件或错误。
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))
【讨论】:
【参考方案5】:我也遇到了这个问题。使用 Python csv
模块,我试图读取在 MS Excel 中创建的 XLS 文件并遇到您遇到的 NULL byte
错误。我环顾四周,找到了xlrd Python 模块,用于从 MS Excel 电子表格文件中读取和格式化数据。使用xlrd
模块,我不仅能够正确读取文件,而且还可以访问文件的许多不同部分,这是我以前无法做到的。
我认为它可能会对你有所帮助。
【讨论】:
感谢您指出该模块。有趣的是,我去下载它并注意到作者正是@John_Machin,他也是这个问题的最高评论。【参考方案6】:将源文件的编码从 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)
【讨论】:
【参考方案7】:你为什么要这样做?
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:意味着他得到了和以前一样的答案。现实情况是他正在处理一个变色龙或变形文件......当他用od
转储它或在文本编辑器中查看它时,它看起来就像一个完全正常的 CSV 文件。然而,当他使用 Python repr() 转储前几个字节时,它就像一个 Excel .XLS 文件(已重命名为具有 CSV 扩展名)。
@John Machin:“一个 Excel .XLS 文件(已重命名为具有 CSV 扩展名”)这是有道理的,它根本无法处理。
@S.Lott:有了这些内容,csv 模块无法处理它是有道理的;但是 xlrd 模块可以处理它。明智地,两个模块都不会从输入文件的名称中推断出任何东西,如果输入确实是一个有名称的文件。
@John Machin:“两个模块都没有从输入文件的名称中推断出任何东西”。真的。我的应用程序框架取决于这个事实。我们不相信文件名意味着什么,因为人们会犯错误(“谎言”)。所以我们必须检查一堆备选方案,直到点击一次。【参考方案8】:
显然它是一个 XLS 文件,而不是一个 CSV 文件,因为 http://www.garykessler.net/library/file_sigs.html 确认
【讨论】:
不一定,但是是的,这可能是一个原因。当我尝试从 XLSX 文件解析 Excel 保存的 CSV 文件时,我确实收到了这个错误。 有了这个幻数是因为 XLSX 有不同的幻数【参考方案9】:我对字符串使用读取文件和拆分函数,而不是 csv 阅读器:
lines = open(input_file,'rb')
for line_all in lines:
line=line_all.replace('\x00', '').split(";")
【讨论】:
【参考方案10】:我遇到了同样的错误。以 UTF-8 保存文件,它可以工作。
【讨论】:
您可能收到相同的错误消息,但原因会有所不同——您最初可能将其保存为 UTF-16(记事本称为“Unicode”)。【参考方案11】:这发生在我使用 OpenOffice Calc 创建 CSV 文件时。当我在文本编辑器中创建 CSV 文件时没有发生这种情况,即使我后来使用 Calc 对其进行了编辑。
我通过在文本编辑器中将 Calc 创建的文件中的数据复制粘贴到新的编辑器创建的文件中解决了我的问题。
【讨论】:
【参考方案12】:我在打开从 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...
免责声明: 请注意,这会覆盖您的原始数据。确保您有它的备份副本。您已被警告!
【讨论】:
【参考方案13】:我通过Excel的“另存为”打开并保存了原始的csv文件为.csv
文件,NULL字节消失了。
我认为我收到的文件的原始编码是双字节 unicode(每隔一个字符就有一个空字符),所以通过 excel 保存它修复了编码。
【讨论】:
【参考方案14】:对于那些讨厌“rU”文件模式的人:我刚刚尝试在 Mac 上使用“rb”文件模式从 Windows 机器打开一个 CSV 文件,但我从 csv 模块收到了这个错误:
Error: new-line character seen in unquoted field - do you need to
open the file in universal-newline mode?
在 'rU' 模式下打开文件可以正常工作。我喜欢通用换行模式——它为我省去了很多麻烦。
【讨论】:
【参考方案15】:我在使用 scrapy 并获取压缩的 csv 文件时遇到了这种情况,而没有正确的中间件来解压缩响应正文,然后再将其交给 csvreader。因此该文件并不是真正的 csv 文件,并相应地引发了 line contains NULL byte
错误。
【讨论】:
嘿伙计,你能解释一下吗,你是如何配置正确的 csv.middleware 的?我得到了和你描述的一样的错误:( @y.y 当然,这是我写的gist.github.com/Gesias/b9ae4593ae7ba7584bf6bcf295f18ffd【参考方案16】:您是否尝试过使用 gzip.open?
with gzip.open('my.csv', 'rb') as data_file:
我试图打开一个已压缩但扩展名为“.csv”而不是“csv.gz”的文件。这个错误一直出现,直到我使用 gzip.open
【讨论】:
【参考方案17】:一种情况是 - 如果 CSV 文件包含空行,则可能会出现此错误。在我们继续写入或读取之前检查行是必要的。
for row in csvreader:
if (row):
do something
我通过在代码中添加此检查解决了我的问题。
【讨论】:
以上是关于Python CSV 错误:行包含 NULL 字节的主要内容,如果未能解决你的问题,请参考以下文章
python csv文件打开错误:_csv.Error: line contains NULL byte
Python JSON to CSV - 编码错误,UnicodeDecodeError:'charmap'编解码器无法解码字节