2012-12-18 59 views
-3

有沒有什麼辦法可以在不加載緩衝區中的所有內容的情況下讀取和寫入文件?使用高效的文件

+0

請給我們一個完整的完整的例子,最好是一個工程。 – NPE

+1

你的問題並非不合理。但請提供一些更多信息,一些技術術語可能會讓一些人感到困惑,而且緩衝區一詞有多種含義。單詞加載也是如此,你的願望對於回答你的問題很重要。 –

+0

我不得不說,我很驚訝這個問題投得多少,它是一個非常好的問題,並且有一些非常好的答案,我認爲它可以從更多的內容和一些編輯中受益。但問題也很簡單。有時最大的拐點是如何有效地處理文件中的所有數據。 –

回答

4

文件對象是可迭代:

with open(filename) as f: 
    for line in f: 
     do_something(line) 

遍歷他們在同一時間產生1線(並且不存儲在內存中的整個文件)


寫入文件也很容易:

with open(filename,'w') as f: 
    for x in get_data(): 
     f.write(x) 

或者你可以使用傳入發生器的方法writelines。例如f.writelines(get_data())

其中get_data可以定義爲:

def get_data(): 
    for i in xrange(200): 
     yield '%d\n'%i 
+0

這只是一個非常簡單的[生成器函數](http://wiki.python.org/moin/Generators)... – mgilson

1

當然可以。例如,以下內容一次只查看一行文件:

with open('data.txt') as f: 
    for line in f: 
     print line.strip() 

這不會將整個文件加載到內存中。

3

您可以使用seek轉到要讀取的文件部分。

從文檔:

要更改文件對象的位置,使用f.seek(偏移,from_what)。 該位置是通過將偏移量添加到參考點來計算的; 參考點由from_what參數選擇。一個from_what 值從文件的開頭開始,1使用當前的 文件位置,2使用文件的結尾作爲參考點。 from_what可以省略,默認爲0,以 文件的開頭爲參考點。

尋找後,您可以讀取字節或行,就像您最初正常加載的文件一樣。

這裏是一個例子函數:

def special_read_file(filename, location, length): 
    file_handle = open(filename) 
    file_handle.seek(location, 0) 
    return file_handle.read(length) 

位置和長度的單位是字節。 file_name將是您要讀取的文件的位置的字符串。

你可以做一些有趣的事情與尋求。使用它在文件中跳轉,這樣就不必在本地存儲文件內容,並且它仍然允許您遍歷行。

作爲一些其他答案已經提到,使用withfor line in file迭代文件行是保持內容在系統上亮起的好方法。但傳遞一個file_handle要簡單得多,你不必保持打開和關閉或讀取它的一部分,你可以打開一個句柄,然後當你需要該特定文件時,從你需要的地方讀取。

在這裏,我寫了一個生成器函數,它可以像平常一樣工作,只有你可以指定文件的哪一部分開始讀取。

def read_handle_from(file_handle, start_point): 
    file_handle.seek(start_point, 0) 
    for line in file_handle: 
     yield line 

my_file_handle = open(file_name) 
for line in read_handle_from(my_file_handle, 2000): 
    #do stuff 

,你可以很容易地修改函數來限制量線的讀,或字節的閱讀量不過你想要的。

它很容易地創建自己的功能和發電機的使用你怎麼想,不要害怕做在Python自己的函數,而不是一切都需要是內置的。

+0

我通常會想'seek'用於不同於'for line in file'的情況。 (只有一小部分問題在使用時纔有意義)。具體而言,我通常更多地使用'seek'來查找'binary'文件。對於ascii,你通常不知道行的開始/結束位置,所以你可以在行的中間尋找垃圾數據。無論如何,很好的答案。 +1 – mgilson

+0

@mgilson謝謝,我知道這可能不是尋求的主要功能,我個人以這種方式使用它,但具有更強大的功能,它可以找到最近的換行符,因此我可以從「大約2000字節的5行「或其他一些這樣的廢話。另外,它更快地尋找一個文件的一部分,而不是迭代說100行,並忽略它們,直到你達到你想要的。 (也是 - 很多「報告」文件最後都有一些有趣的內容,這樣我可以尋找文件的末尾並從中讀取一些行)。 –

+0

@InbarRose就個人而言,對於那些用例,我傾向於' mmap'文件 –

1

File對象,是可迭代的,所以你可以做你想象中的事情。

例如,寫從輸入到輸出每隔一行,使用類似:

from itertools import islice 
with open('input') as fin, open('output', 'w') as fout: 
    every_other = islice(fin, None, None, 2) 
    fout.writelines(every_other) 
+1

+1 - 我喜歡itertools.islice - 儘管您可能想鏈接到文檔,以便OP不喜歡「在這個世界上有什麼是那些'沒有'在那裏? 。 – mgilson