我正在使用一些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在输出中(或\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()
Run Code Online (Sandbox Code Playgroud)
顺便问一下,你是否用文本编辑器查看了文件(包括最后几行)?它实际上看起来像一个合理的CSV文件,像另一个(没有"NULL字节"异常)文件?
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)
这适合我.
小智 11
将源文件的编码从UTF-16转换为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)
如果要假装它们不存在,您可以内联生成器来过滤掉空值.当然这是假设空字节实际上不是编码的一部分,实际上是某种错误的工件或错误.
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)
你为什么做这个?
\n\n reader = csv.reader(open(filepath, "rU"))\nRun Code Online (Sandbox Code Playgroud)\n\n文档非常清楚你必须这样做:
\n\nwith open(filepath, "rb") as src:\n reader= csv.reader( src )\nRun Code Online (Sandbox Code Playgroud)\n\n模式必须是“rb”才能读取。
\n\nhttp://docs.python.org/library/csv.html#csv.reader
\n\n\n\n如果 csvfile 是文件对象,则必须在有影响的平台上使用 \xe2\x80\x98b\xe2\x80\x99 标志打开它。
\n