Python 按行讀取文本文件 緩存 和 非緩存實現
需求
最近項目中有個讀取文件的需求,數據量還挺大,10萬行的數量級。
java 使用緩存讀取文件是,會相應的創建一個內部緩沖區數組在java虛擬機內存中,因此每次處理的就是這一整塊內存。
簡單的想:就是如果不用緩存,每次都要硬盤–虛擬機緩存–讀取;有了緩存,提前讀了一段放在虛擬機緩存里,可以避免頻繁將硬盤上的數據讀到緩存里。
因為對內存的操作肯定是比硬盤的操作要快的。
對了,java還有映射內存,可以解決大文件讀寫的問題。
思路
大文件讀寫不能一次全部讀入內存,這樣會導致耗盡內存。(但是在內存允許的情況下,全部讀入內存是不是速度更快??)
對于大文件可以一行一行讀取,因為我們處理完這行,就可以把它拋棄。
我們也可以一段一段讀取大文件,實現一種緩存處理。每次讀取一段文件,將這段文件放在緩存里,然后對這段處理。這會比一行一行快些。
方法1:一行一行讀取
我們可以打開一個文件,然后用for循環讀取每行,比如:
def method1(newName): s1 = time.clock() oldLine = '0' count = 0 for line in open(newName): newLine = line if (newLine != oldLine): #判斷是不是空行 if newLine.strip(): nu = newLine.split()[0] oldLine = newLine count += 1 print "deal %s lines" %(count) e1 = time.clock() print "cost time " + str(e1-s1)
我們測試一下
fileName = 'E:\\pythonProject\\ruisi\\correct_re.txt' method1(fileName)
輸出
deal 218376 lines cost time 0.288900734402
方法1.1 一行一行讀取的變形
def method11(newName): s1 = time.clock() oldLine = '0' count = 0 file = open(newName) while 1: line = file.readline() if not line: break else: if line.strip(): newLine = line if (newLine != oldLine): nu = newLine.split()[0] oldLine = newLine count += 1 print "deal %s lines" %(count) e1 = time.clock() print "cost time " + str(e1-s1)
deal 218376 lines cost time 0.371977884619
耗時和方法1差不多,比方法1稍微多些。
方法2:一行一行,使用fileinput模塊
def method2(newName): s1 = time.clock() oldLine = '0' count = 0 for line in fileinput.input(newName): newLine = line if newLine.strip(): if (newLine != oldLine): nu = newLine.split()[0] oldLine = newLine count += 1 print "deal %s lines" %(count) e1 = time.clock() print "cost time " + str(e1-s1)
deal 218376 lines cost time 0.514534051673
這兒的耗時差不多是方法1的兩倍。
借助緩存,每次讀取1000行
def method3(newName): s1 = time.clock() file = open(newName) oldLine = '0' count = 0 while 1: lines = file.readlines(10*1024) #print len(lines) if not lines: break for line in lines: if line.strip(): newLine = line if (newLine != oldLine): nu = newLine.split()[0] oldLine = newLine count += 1 print "deal %s lines" %(count) e1 = time.clock()
Note
readlinessizehint() 參數是限定字節大小,不是行數。
注意默認有個內部緩沖區大小是8KB,如果設定值小于 8*1024。那么都是按照8KB來的。print len(lines)
輸出大概都為290。
只有當設定值大于8KB,上面的print len(lines)
才會發生變化。
deal 218376 lines cost time 0.296652349397
這兒的性能還沒方法1,表現好。可以調整每次讀取的行數,比如500,1000等等,可以達到不同的耗時。
方法4 一次性全部讀到內存里
def method4(newName): s1 = time.clock() file = open(newName) oldLine = '0' count = 0 for line in file.readlines(): if line.strip(): newLine = line if (newLine != oldLine): nu = newLine.split()[0] oldLine = newLine count += 1 print "deal %s lines" %(count) e1 = time.clock() print "cost time " + str(e1-s1)
輸出
deal 218376 lines cost time 0.30108883108
結論
推薦使用
with open('foo.txt', 'r') as f: for line in f: # do_something(line)
對于大文件可以使用索引,這個索引記錄下每行開頭的位置,之后就可以用file.seek()定位了。如果文件內容修改了,還需要重新建立索引。這個索引可以有很多種方法建立,但是都需要將文件遍歷一次。
參考資料
本文由用戶 SylArmenta 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!