2010-10-11 46 views
56

對於我正在做的練習,我試圖用read()方法讀取給定文件的內容兩次。奇怪的是,當我第二次調用它時,它似乎沒有將文件內容作爲字符串返回?爲什麼我不能在打開的文件上調用read()兩次?

這是我知道這是不是最有效或最佳方式代碼

f = f.open() 

# get the year 
match = re.search(r'Popularity in (\d+)', f.read()) 

if match: 
    print match.group(1) 

# get all the names 
matches = re.findall(r'<td>(\d+)</td><td>(\w+)</td><td>(\w+)</td>', f.read()) 

if matches: 
    # matches is always None 

當然,這是不是這裏的點。問題是,爲什麼我不能撥打read()兩次?我必須重置文件句柄嗎?或者關閉/重新打開文件,以此來做到這一點?

+2

你從哪裏得到讀取不會改變文件狀態的想法?您使用的是什麼參考或教程? – 2010-10-11 12:29:31

+0

我相信關閉和重新打開該文件應該基於下面的anwers工作。 – Anthony 2010-10-11 12:29:59

+0

@Shynthriir:關閉並重新打開文件並不總是一個好主意,因爲它可能在系統中有其他影響(臨時文件,incron等)。 – 2010-10-11 12:32:22

回答

88

調用read()會讀取整個文件,並將讀取光標保留在文件的末尾(沒有其他可讀的內容)。如果您想要一次讀取一定數量的行,則可以使用readline()readlines()或通過與for line in handle:重複行。

要直接回答您的問題,一旦讀取了文件,使用read(),您可以使用seek(0)將讀取光標返回到文件的開頭(文檔是here)。如果您知道該文件不會太大,您還可以將read()輸出保存到變量中,並在findall表達式中使用它。

Ps。不要忘了在完成之後關閉文件;)

+3

+1,是的,請閱讀臨時變量避免不必要的文件I/O。這是一個虛假的經濟,因爲你有更少的(顯式)變量,所以你正在保存任何內存。 – 2010-10-11 13:45:03

+2

@NickT:我期望一個被多次讀取的小文件被操作系統緩存(至少在Linux/OSX上),所以沒有額外的文件I/O來讀取兩次。不適合內存的大文件不會被緩存,但您不想將它們讀入變量,因爲您將開始交換。所以如有疑問,請多閱讀一次。如果你確定文件很小,那麼請做出最好的程序。 – Claude 2014-06-04 13:41:04

+0

使用['with'](http://effbot.org/zone/python-with-statement.htm)可以實現自動拆除。 – 2016-01-19 16:47:56

13

讀指針移到最後讀取的字節/字符之後。使用seek()方法將讀指針倒回到開頭。

2

每個打開的文件都有一個關聯的位置。
當你閱讀()你從那個位置讀取。 例如read(10)從新打開的文件中讀取前10個字節,然後另一個read(10)讀取下10個字節。 read()無參數讀取文件的所有內容,並將文件位置保留在文件末尾。您下次撥打read()時,沒有什麼可讀的。

您可以使用seek移動文件位置。或者在你的情況下可能更好的做一個read()並保持兩種搜索的結果。

13

到目前爲止回答這個問題的人都是絕對正確的 - read()在文件中移動,因此在調用它之後,不能再調用它。

我要補充的是,在你的特殊情況下,你不需要重新開始或重新打開文件,你可以將你讀過的文本存儲在局部變量中,然後使用兩次或多次,只要你喜歡,在你的程序:

f = f.open() 
text = f.read() # read the file into a local variable 
# get the year 
match = re.search(r'Popularity in (\d+)', text) 
if match: 
    print match.group(1) 
# get all the names 
matches = re.findall(r'<td>(\d+)</td><td>(\w+)</td><td>(\w+)</td>', text) 
if matches: 
    # matches will now not always be None 
+1

+1其實這是本練習的建議解決方案(http://code.google.com/intl/de-DE/edu/languages/google-python-class/exercises/baby-names.html)。但不知何故,我沒有想到將字符串存儲在變量中。 D'哦! – helpermethod 2010-10-11 17:33:23

+1

在Python3中,使用pathlib。 '從pathlib導入路徑; text =路徑(文件名).read_text()'照顧打開,關閉等。 – PaulMcG 2017-06-19 12:06:20

1

read()消耗。所以,你可以重置這個文件,或者重新開始閱讀之前。或者,如果它適合您的任務,則可以使用read(n)僅消耗n字節。

12

是的,如上...

我會寫只是一個例子:

>>> a = open('file.txt') 
>>> a.read() 
#output 
>>> a.seek(0) 
>>> a.read() 
#same output 
1

我總是覺得散步的讀法的東西下來一個黑暗的衚衕。你稍微停下來,但如果你不計算你的步數,你不知道你有多遠。 Seek通過重新定位給出解決方案,另一個選項是Tell,它返回文件的位置。可能是Python文件API可以將讀取和查找結合到一個read_from(位置,字節)以使其更簡單 - 直到發生這種情況,您應該閱讀this page

相關問題