2010-12-17 63 views
6

假設我在美國擁有10GB硬盤Ubuntu VPS(並且我居住在其他地方),並且硬盤上有9GB文本文件。我有512MB的RAM,和大約相同數量的交換。如何在有限的環境中從Python中的大文件中刪除行

鑑於我無法添加更多硬盤空間並且無法將文件移動到其他地方進行處理,是否有一種有效的方法可以使用Python從文件中刪除某些行(最好是其他任何語言都可以接受) ?

回答

3

這個怎麼樣?它編輯文件到位。我已經在一些小文本文件(在Python 2.6.1中)上測試過它,但我不確定它會在大量文件上執行的效果如何,因爲所有的跳轉,但仍然...

我'因爲for line in f:沒有正常工作(大概所有的跳躍都會影響正常的迭代),所以我使用了無限期的while循環和手動EOF檢查。可能有更好的方法來檢查這一點,但我對Python相對來說比較陌生,所以有人請讓我知道是否有。

此外,您需要定義功能isRequired(line)

writeLoc = 0 
readLoc = 0 
with open("filename" , "r+") as f: 
    while True: 
     line = f.readline() 

     #manual EOF check; not sure of the correct 
     #Python way to do this manually... 
     if line == "": 
      break 

     #save how far we've read 
     readLoc = f.tell() 

     #if we need this line write it and 
     #update the write location 
     if isRequired(line): 
      f.seek(writeLoc) 
      f.write(line) 
      writeLoc = f.tell() 
      f.seek(readLoc) 

    #finally, chop off the rest of file that's no longer needed 
    f.truncate(writeLoc) 
+0

+1:幾乎完全是我的解決方案,但填寫了所有不清楚的細節。並經過測試。 – 2010-12-17 11:55:03

+1

優秀的解決方案。 – 2010-12-17 12:18:01

+0

感謝您的建議,我有點擔心,如果在此過程中發生任何錯誤,我的文件將不會處於原始狀態?考慮到行號實際上重要的事實是需求(行)功能。我知道我可以登錄/寫入一個文件以「記住」已更改的內容,並在之後繼續,但我想看看是否有一種非常努力的方式來實現這一點。 – 2010-12-17 12:22:56

0

只需按順序讀取和寫入文件。

f.readlines()返回一個包含 文件數據的所有行的列表 。如果給定一個可選的 參數大小提示,它會讀取文件中的許多 字節,並且有足夠多到 完成一行,並從中返回行 。 這通常用於允許 通過 行高效地讀取大文件,但不必將整個文件加載到內存中。只有完成 行將被退回。

Source

+0

寫在哪裏?沒有足夠的空間。 – khachik 2010-12-17 10:45:06

+0

這取決於我認爲的體系結構/文件系統......但我想說你無法修改這個意義上的文件,你需要重新編寫它。 – phant0m 2010-12-17 10:54:23

0

進程中的文件中獲取10/20或多個MB塊。 這將是最快的方法。

這樣做的其他方式是流式傳輸此文件並使用AWK進行過濾。

例如僞代碼:

file = open(rw) 
linesCnt=50 
newReadOffset=0 
tmpWrtOffset=0 
rule=1 
processFile() 
{ 
    while(rule) 
    { 
     (lines,newoffset)=getLines(file, newReadOffset) 
     if lines: 
      [x for line in lines if line==cool: line] 
      tmpWrtOffset = writeBackToFile(file, x, tmpWrtOffset) #should return new offset to write for the next time 
     else: 
      rule=0 
    } 
} 

要在最終用途truncate(size=None)

+0

'-1 hater'請解釋你爲什麼認爲這是廢話? – bua 2010-12-17 10:52:16

+4

你爲什麼要爲Python編寫僞代碼?對於這個問題,你爲什麼要編寫看起來比Python通常更低級的僞代碼? – 2010-12-17 10:59:44

+0

因爲我沒有可能檢查它是否在運行,我不是本機Python程序員。這應該只是給出一個想法,他應該知道什麼。最終代碼看起來不是我的問題...... – bua 2010-12-17 11:05:05

2

調整文件試試這個:

currentReadPos = 0 
removedLinesLength = 0 
for line in file: 
    currentReadPos = file.tell() 
    if remove(line): 
     removedLinesLength += len(line) 
    else: 
     file.seek(file.tell() - removedLinesLength) 
     file.write(line + "\n") 
     file.flush() 
    file.seek(currentReadPos) 

我沒有運行它,但這個想法是修改通過用想要保留的行覆蓋要刪除的行來實現文件。我不確定查找和修改如何與迭代文件進行交互。

+0

+1提供相關/有用的信息 – 2010-12-17 12:53:55

1

更新

我已經通過創建一個1GB的文件試圖fileinput就地。我的預期與發生的事情不同。我這次正確閱讀文檔。

可選就地過濾:如果= 1被傳遞 的 關鍵字參數就地到fileinput.input()或到 的FileInput構造函數,該文件是 移動到備份文件和標準 輸出是指向輸入文件 (如果一個與 備份文件同名的文件已經存在,則將以 默默取代)。

docs/fileinput

所以,這似乎不是一個選擇,現在你。請檢查其他答案。


編輯之前:

如果您正在尋找編輯文件就地,然後檢查了Python的fileinput模塊 - Docs

我真的不確定它在使用10GB文件時的效率。但是,對我來說,這似乎是你使用Python的唯一選擇。

+0

感謝,+1提供相關答案。 – 2010-12-17 12:52:25