2010-11-05 62 views
2

我想從gzip文件逐行讀回。我知道ReadBackwards模塊,但是如何才能使它在gzip文件上工作?我應該使用不同的模塊嗎?Perl回讀和gzip文件

+2

到目前爲止的答案已經解釋了爲什麼你不能做你想做的。可能還有其他選擇;你能否提供關於實際目標的更多細節,文件中包含了哪些內容,爲什麼在你看到它之前無法分辨你需要多少內容?例如,可能兩步法的工作? – Porculus 2010-11-06 00:26:26

+0

@Poculus - 兩種方法都可以。但是,我最終採取了chas的方法。我的問題是我有非常大的日誌文件,其中包含有關幾個不同主題的消息。對於每個主題,我需要在最後一行之前立即獲取一行條件(一個複雜的正則表達式)爲真。這通常意味着我需要讀取不超過文件末尾的1-2%,但偶爾,我從底部讀取10-20%,在最壞的情況下,我不得不增加文件的50%。 – 2010-11-08 15:22:18

回答

7

爲什麼你想要反向閱讀?嘗試向後讀取壓縮文件沒有性能提升。您必須首先對其進行解壓縮(以瞭解哪個字節n意味着您必須首先解壓縮字節0 .. n)。

你可能不會在比速度方面得到更好的:

#!/usr/bin/perl 

use strict; 
use warnings; 

die "usage: $0 filename" unless defined(my $file = shift); 

open my $fh, "<:gzip", $file 
    or die "could not open $file: $!"; 

my @lines; 
while (<$fh>) { 
    push @lines, $_; 
    shift @lines if @lines > 10; 
} 

print @lines; 
+0

我不在乎如果尋求到最後是緩慢的。我想避免的是不得不將整個文件存儲在內存中。我不知道,直到我已經處理了他們需要的線數。我特別沒有保證我不需要閱讀整個文件。 – 2010-11-05 23:00:03

+0

@pythonic隱喻你需要將它解壓縮到一個文件,然後使用'File :: Backwards'來讀取它。 – 2010-11-05 23:06:16

4

你幾乎需要首先解壓文件。你不能(很容易)隨機地尋找gziped文件。

+0

我處於相關文件相當大的情況,準確地說有幾個GB,並且我不知道需要提前從底部處理多少行。 – 2010-11-05 22:56:30

+1

@pythonic然後沒有辦法做你想做的事情,不是很慢。週期性流重置的gzip可以稍微尋找(不是來自PerlIO內部,但是您可以編寫使用它的代碼)。 gzip *沒有*週期性流重置是100%不可檢測的,這可能是你的。 – hobbs 2010-11-06 00:11:21

0

不要存放在內存中的文件。將它存儲在SQLite或類似的數據庫中,並在讀取並插入數據庫時​​使用行號的順序索引字段。

當文件完全存儲在數據庫中時,通過使用降序對索引進行排序來向後走行。您可以根據需要快速瀏覽數據庫,並且可以使用數據庫查詢來定位行。如果你擁有大量的RAM或者固態硬盤,速度不會那麼快,但是比試圖處理一個壓縮文件要快得多,就像你正在談論的那樣。

計算機編程全都是在限制範圍內尋找創造性解決方案。你受RAM的限制以及你使用壓縮文件的事實。您必須解壓縮文件以向後走,但無法將其放入RAM中。所以,你必須把數據放在某個地方,而且這幾乎離開了磁盤。在數據庫中往回走是比平面文件更容易,因此,請使用數據庫來查看它的優點,然後繼續前進。

0

我沒有測試這個偉大的方法,但是從this post我認爲你可以打開該文件

open my $handle, '-|', '/usr/bin/gzcat', $filename; 

這將允許你通過文件中的行由行步如

foreach my $line (<$handle>) { 
    do stuff with $line ... 
} 

我的理解是,這不會啜泣整個文件,應該幫助大文件上的內存。如果我對這個問題有錯,希望有人會來拍我一條魚。

我也知道這是前進的,但我對你的希望是,現在你不需要從記憶的角度來倒退。如果你仍然這樣做,也許你可以做一些修改來將它用於File :: Backwards。現在

,我似乎並不有我(的Ubuntu)系統上gzcat,但我發現很多是說gzcat相同zcatgunzip -cgzip -dc等程序名因人而異引用。我再次希望這種方法是健全的。