2012-06-14 164 views
1

我有一個巨大的文件(1.2GB)的特徵向量保存爲csv文件。 爲了通過這些界限,我創建了一個python類,它可以一次一個批次地從巨型文件中將行加載到內存中。python,尋找,告訴,閱讀。從巨型csv文件讀取行

爲了讓這個類知道在文件中準確讀取批量batch_size的完整行(可以說batch_size = 10,000),在第一次使用巨型文件時,這個類會遍歷整個文件一次,並註冊每行的偏移量,並將這些偏移量保存到幫助文件中,以便稍後它可以「file.seek(starting_offset); batch = file.read(num_bytes)」讀取下一批行。

首先,我實現了線偏移的報名以這種方式:

offset = 0; 
    line_offsets = []; 
    for line in self.fid: 
     line_offsets.append(offset); 
     offset += len(line); 

和它的工作與可愛giant_file1。

但隨後我在這個類的幫助下處理了這些特性並創建了giant_file2(具有標準化的特性)。 接下來,當我想讀取批量的行格式giant_file2時,它失敗了,因爲它將讀取的批處理字符串不在正確的位置(例如,讀取類似「-00 \ n15.467e-04」,.. 。「而不是」15.467e-04,... \ n「)。

因此,我試圖改變線偏移計算部分:

offset = 0; 
    line_offsets = []; 
    while True: 
     line = self.fid.readline(); 

     if (len(line) <= 0): 
      break; 

     line_offsets.append(offset); 
     offset = self.fid.tell(); 

代替線的累積長度,主要的變化是,偏移寄存器我從fid.tell的結果取()。

該版本與giant_file2配合良好,但與giant_file1失敗。

我進一步調查了它,發現函數seek(),tell()和read()彼此不一致。 例如:

fid = file('giant_file1.csv'); 
fid.readline(); 
>>>'0.089,169.039,10.375,-30.838,59.171,-50.867,13.968,1.599,-26.718,0.507,-8.967,-8.736,\n' 
fid.tell(); 
>>>67L 
fid.readline(); 
>>>'15.375,91.43,15.754,-147.691,54.234,54.478,-0.435,32.364,4.64,29.479,4.835,-16.697,\n' 
fid.seek(67); 
fid.tell(); 
>>>67L 
fid.readline(); 
>>>'507,-8.967,-8.736,\n' 

有一些矛盾在這裏:當我(按fid.tell())在67字節定位一次讀取的行是一回事,並在第二次(FID再次當.tell()報告我位於字節67)讀取的行是不同的。

我不能相信tell()和seek()將我放到想要的位置,從所需行的開頭讀取。 在另一方面,當我使用(與giant_file1)字符串的長度作爲參考的尋求()我得到正確的位置:

fid.seek(0); 
line = fid.readline(); 
fid.tell(); 
>>>87L 
len(line); 
>>>86 
fid.seek(86); 
fid.readline(); 
>>>'15.375,91.43,15.754,-147.691,54.234,54.478,-0.435,32.364,4.64,29.479,4.835,-16.697,\n' 

這是怎麼回事呢?

我能想到的giant_file1和giant_file2之間的唯一區別是,在giant_file1中,值是用小數點(例如-0.435)寫的,在giant_file2中它們都是科學格式(例如-4.350e-01) 。我不認爲他們中的任何一個都是用unicode編碼的(我認爲是這樣,因爲我用簡單的file.read()讀取的字符串似乎可讀,我怎麼確定?)。

我非常感謝您的幫助,解釋,理由和可能的解決方案(或解決方法)。

謝謝, Yonatan。

+3

是否有理由不能在處理文件時迭代文件行 –

+3

除此之外,爲什麼不使用[csv'模塊](http://docs.python.org/library/csv .html),它允許你逐行處理? –

+0

我同意@Jakob Bowyer,在計算偏移量時,你反覆遍歷整個文件中的所有行。那麼,爲什麼不處理呢? – Dhara

回答

2

我認爲你有一個換行符問題。檢查giant_file1.csv是否以\ n或\ r \ n結尾行如果以文本模式打開該文件,該文件將返回僅以\ n結尾的行,並丟棄多餘的\ r。所以,當你查看返回的行的長度時,它將是實際文件位置的1(它不僅消耗了\ n,而且還消耗了\ r \ n)。當然,當你閱讀更多的行時,這些錯誤會累積下來。

解決的辦法是以二進制模式打開文件。在這種模式下,沒有\ r \ n - > \ n減少,所以您的行長度符合您的文件tell()查詢。

我希望能爲你解決它 - 因爲這是一個簡單的解決方案。 :)祝你的項目和快樂的編碼!

+0

聽起來很可能是問題所在。 – martineau

+0

就是這樣。謝謝。 – user1456524

+0

謝謝你們的建議。實際上,我只嘗試了第一種解決方案 - 我使用模式「rb」(讀,二進制)而不是「r」打開文件,並解決了問題:1)現在讀取的字符串長度與告訴()。 2)在giant_file2(在Windows中創建)中,讀取的字符串中有'\ r \ n'字符。謝謝你,Yonatan。 – user1456524