2011-11-15 99 views
1

我有一系列大的平面文本文件,爲了插入到SQL數據庫中,我需要解析它們。每條記錄跨越多行,由大約一百個固定長度的字段組成。我想弄清楚如何在不將整個文件加載到內存的情況下高效地解析它們。在Python中高效地解析大型文本文件?

每條記錄​​都以一個數字「1」開始,作爲新行的第一個字符(儘管不是所有以「1」開頭的行都是新記錄),並在稍後用一系列20個空格終止多行。雖然每個字段都是固定寬度,但每個記錄都是可變長度的,因爲它可能包含或不包含多個可選字段。所以我一直在使用"...20 spaces...\n1"作爲記錄分隔符。

我一直試圖在同一時間像這樣的東西來處理1KB工作:

def read_in_chunks(file_object, chunk_size): 
    while True: 
     data = file_object.read(chunk_size) 
     if not data: 
      break 
     yield data 

file = open('test.txt') 
for piece in read_in_chunks(file, chunk_size=1024): 
    # Do stuff 

但是,我快到問題是,當一個記錄跨越多個數據塊。我忽略了一個明顯的設計模式?這個問題似乎有點普遍。謝謝!

+0

好吧,我重新閱讀這個問題......爲什麼不解析文件一次只是作爲通讀來獲得所有記錄的記錄位置的結束......然後通過將這些值饋送到您的塊大小 – RobotHumans

+0

@ aking1012:謝謝。自從我寫這個問題以來,這就是我一直在努力的方法。但是,一次讀取一個字節需要花費很長時間,並且一次讀取多個字節仍然會導致數據跨越多個塊的問題。我確信在我面前有一個明顯的解決方案。 – jamieb

+0

是的,如果你一次讀兩個塊......那麼問題就解決了。在C中它將被實現爲循環緩衝區。除了讀取兩個塊並將其轉換爲python之外,我還沒有看到一個快速的循環緩衝區實現。如果你同時使用兩個塊,使用rstrip/lstrip並獲得大小差異可能是有效的......但我沒有加載測試它。 – RobotHumans

回答

3
def recordsFromFile(inputFile): 
    record = '' 
    terminator = ' ' * 20 
    for line in inputFile: 
     if line.startswith('1') and record.endswith(terminator): 
      yield record 
      record = '' 
     record += line 
    yield record 

inputFile = open('test.txt') 
for record in recordsFromFile(inputFile): 
    # Do stuff 

順便說一句,file是一個內置函數。改變它的價值是不好的風格。

+1

稍微更高效一些,使用列表後面跟着''.join()來創建字符串。 –

+0

我喜歡它,但是如果它是一個大文件,不會將大量數據加載到內存中? – RobotHumans

+0

我不這麼認爲。你爲什麼這麼認爲呢?如果它確實會成爲問題嗎?輸入文件有多大? –