2010-11-12 50 views
77

我與一些CSV文件時,用下面的代碼:Python的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。有什麼辦法可以解決Python中的這個問題嗎?

== == 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字節。

+0

「od -c」表示第一行看起來像什麼? – 2010-11-12 15:22:15

+0

我應該運行什麼查詢,如cat my.csv | od -c |更多 ?我得到:0000000 D e p a r t m e n t F a m i l – AP257 2010-11-12 15:35:13

+0

CSV是如何生成的?從excel中,你可以嘗試一種方言。否則看看說:http://stackoverflow.com/questions/2753022/python-finding-unicode-ascii-problems – 2010-11-12 15:51:37

回答

1

你爲什麼要這麼做?

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

If csvfile is a file object, it must be opened with the ‘b’ flag on platforms where that makes a difference.

+2

謝謝,但沒有幫助... – AP257 2010-11-15 17:27:35

+0

@ AP257:「沒有幫助」?意味着什麼?任何特定的錯誤消息? – 2010-11-15 19:40:55

+1

@ S.Lott:意味着他得到和以前一樣的答案。現實情況是,他正在處理一個變色龍或shapeshifter文件...當他用'od'轉儲它或在文本編輯器中查看它時,它看起來像一個完全正常的CSV文件。但是,當他用Python repr()轉儲前幾個字節時,它就像一個Excel .XLS文件(它已被重命名爲具有CSV擴展名)。 – 2010-11-15 22:01:18

90

正如@美國洛特說,你應該在 'RB' 模式打開你的文件,而不是'儒的模式。但是,這可能不會導致您目前的問題。據我所知,如果在數據中嵌入\r,但使用'rU'模式會讓你感到不適,但不會導致其他任何電視劇。我還注意到,你有幾個文件(都用'rU'??打開),但只有一個導致問題。

如果csv模塊說你有一個「空」(愚蠢的消息,應該是「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(或\0od -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() 

順便說一下,你是否用文本編輯器查看過文件(包括最後幾行)?它實際上看起來像一個合理的CSV文件(沒有「NULL字節」異常)文件嗎?

+0

非常感謝您提供非常詳細的幫助。文件中有很多\ x00個字符(請參閱編輯問題) - 這很奇怪,因爲在文本編輯器中它看起來像一個完全合理的CSV文件。 – AP257 2010-11-15 17:35:09

+1

@ AP257:''\ xd0 \ xcf \ x11 \ xe0 \ xa1 \ xb1 \ x1a \ xe1'是表示OLE2複合文檔文件的「簽名」。一個** Excel 97-2003 .XLS文件**。我發現「在文本編輯器中,它看起來像一個完全合理的CSV文件」是**完全不可信**。您必須一直在查看另一個文件夾,有效的CSV文件,另一個文件夾或另一臺計算機上或其他某個時間。請注意,您的'od'輸出不是來自XLS文件。 – 2010-11-15 21:48:04

+7

@ AP257:您還沒有接受此答案的任何特定原因? – 2011-01-24 05:14:02

2

appparently這是一個XLS文件,而不是一個CSV文件作爲http://www.garykessler.net/library/file_sigs.html確認

+0

不一定,但是,這可能是一個原因。當我嘗試解析由Excel從XLSX文件保存的CSV文件時,我確實收到了此錯誤。 – Cerin 2015-01-22 18:29:20

+0

有了這個神奇的數字,它的原因是XLSX有不同的幻數 – 2015-01-24 14:09:11

12

我碰上了這個問題爲好。使用Python csv模塊,我試圖讀取在MS Excel中創建的XLS文件,並且遇到您遇到的NULL byte錯誤。我環顧四周,發現xlrd Python模塊用於從MS Excel電子表格文件中讀取和格式化數據。使用xlrd模塊,我不僅可以正確讀取文件,還可以以前所未有的方式訪問文件的許多不同部分。

我認爲這可能對你有幫助。

+6

感謝您指出該模塊。有趣的是,我去下載並注意到作者是@John_Machin,也是對這個問題的最高評論。 – Evan 2012-03-19 23:28:31

1

我得到了同樣的錯誤。以UTF-8保存文件,它工作。

+1

您可能得到了相同的錯誤信息,但原因可能會有所不同 - 您可能最初將其保存爲UTF-16(記事本稱爲「Unicode」)。 – 2011-11-29 07:48:13

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

相反CSV閱讀我用讀文件和拆分功能字符串:

lines = open(input_file,'rb') 

for line_all in lines: 

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

這發生在我身上時,我創建了一個CSV與OpenOffice的Calc的文件。當我在文本編輯器中創建CSV文件時,即使我之後使用Calc進行編輯,也不會發生這種情況。

我解決了我的問題,在我的文本編輯器中將我的Calc創建的文件中的數據粘貼到新的編輯器創建的文件中。

1

我有同樣的問題,打開一個CSV服務產生的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

對於所有那些'儒的FILEMODE仇敵:我只是想從Windows機器在Mac上打開一個CSV文件與「RB」 FILEMODE和我從csv模塊這個錯誤:

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

以'rU'模式打開文件可以正常工作。我喜歡通用換行模式 - 它爲我節省了很多麻煩。

15

把它看作UTF-16也是我的問題。

這裏是我的代碼,結束了工作:

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

其中位置是您的CSV文件的目錄。

0

我在使用scrapy和獲取壓縮的csv文件時沒有正確的中間件解壓縮響應主體,然後將其交給csvreader之前遇到此問題。因此,該文件並不是一個真正的csv文件,並相應地拋出了line contains NULL byte錯誤。

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)) 
8
data_initial = open("staff.csv", "rb") 
data = csv.reader((line.replace('\0','') for line in data_initial), delimiter=",") 

這對我的作品。

+0

解決了我的情況,null是'\ 0'值。謝謝。 – 2017-02-12 02:44:26

-1

一種情況是 - 如果CSV文件包含空行,則可能會顯示此錯誤。在我們繼續寫或讀之前檢查行是必要的。

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

我通過在代碼中添加此檢查來解決了我的問題。

相關問題