2013-11-15 82 views
1

我想要了解什麼是最有效(速度和性能)的方式來向後讀取gzip文件,而無需將整個文件的內容加載到內存中。反向讀取gzip文件

這是我目前做的,但效率不高的真正的大文件:

file = 'huge_file.log.gz' 
import gzip 
if file.endswith('gz'): 
    f = gzip.open(file) 
    # reverse the file contents 
    reverse_file_list = reversed(f.read().decode('utf-8').split('\n')) 

我看到有在計算器和codestate一些解決方案,這樣做的負面尋求反而不利尋求在文件中不支持以二進制方式打開與gzip.open

鏈接: Most efficient way to search the last x lines of a file in python

http://code.activestate.com/recipes/439045/

所以解決方案失敗了,我想完成。

回答

1

真的沒有一個好方法。 gzip(deflate)壓縮數據格式在使用霍夫曼代碼和在先前的32K中使用匹配字符串時固有地是串行的。

如果你不能把它全部放到內存中,你需要a)將它解壓縮到磁盤上,並使用未壓縮表單上的查找來反轉它,或者b)通過創建一個解壓縮文件來有效地創建gzip文件隨機訪問入口點足夠小以保留在內存中,然後執行第二次解壓向後傳遞,反轉每個塊。 a)可以用tac完成,正如@Jud的答案中所建議的,因爲tac將在磁盤上創建一個臨時文件來保存未壓縮的內容。 b)複雜,需要對放氣格式有深入的瞭解。它還要求您爲每個入口點保存32K的歷史記錄,無論是在內存中還是在磁盤上。

1

唯一的解決方案可能是將文件解壓縮到磁盤並反轉行順序。它使用磁盤空間的兩倍,但不是內存。

您可以一次同時完成這些步驟:

gzip -cd huge_file.log.gz | tac > huge_file.log.reversed 

然後就可以正常閱讀和處理。

+0

+1使用'TAC ' –

0

不幸的是,您必須從頭開始解析gz文件,並且可能會耗費時間將它們全部解析到最後。我用一個列表緩衝區,如果反向= True和BSIZE已經達到,只是彈出的第一個項目,它總是保持文件的最後BSIZE比賽和一通:

BSIZE = 100; searchstr= "match in gzfile"; n = 0; buffer = []; reversed = True 
    # gzf is an *.gz file in a directory 
    with gzip.open(files['path'] + '/' + gzf, 'rt') as f: 
     for line in f: 
      if re.search(searchstr, line): 
       n += 1 
       buffer.append(line.strip()) 
       if n >= BSIZE and not reversed: 
        break 
       elif n >= BSIZE: 
        buffer.pop(0)