2012-09-21 41 views
0

我想在Windows中使用Perl解析大* .gz文件。Perl - 在Windows中解析巨大的* .gz文件

在Solaris中,我可以使用下面的結構:

my $cmd = "zcat $dir/$file|"; 
open FILE, $cmd or die "$cmd:$!"; 

while (<FILE>) { 
. 
. 
. 
} 

,它工作正常。在Windows中,我打算使用IO::Zlib模塊,例如,

my $fh = IO::Zlib->new("$file", "rb"); 
while (my $line = $fh->getline()) { 
. 
. 
} 

但我內存不足。 (我的系統有4GB RAM)。有沒有其他方法來解析大* .gz文件?

+0

爲什麼你就不能處理之前解壓呢?磁盤空間不足? –

+0

你對循環內部的行做了些什麼嗎?另外,如果你的文件有外部行結尾,perl可能會啜泣文件(IO :: Zlib使用明確的'\ n'而不是'$ /')。 – TLP

回答

2

爲什麼不直接安裝Gzip for Windows(其中包括zcat)?除了您遇到的內存問題,我發現gzip的管道比使用IO::Zlib的管道更快。 (這是有幾個原因的,$fh->getline是一個方法調用,Perl的方法調用並不是最快的,而且,外部運行gzip利用了多任務處理,現在多核心機器很常見,這一點很明顯。)

由於某些原因,GnuWin提供zcat作爲shell腳本,而這在Windows下不起作用。但是您可以使用gzip -cd而不是zcat(這也應該在Unix平臺上運行)。

+0

嗯,聽起來不錯。我會嘗試。你認爲你可以告訴我,如何在windows中使用gzip管道? – taiko

+0

與在Solaris上執行操作的方式相同。你只需要在'PATH'上加上'zcat'(與Solaris相同)。 – cjm

+0

我已經安裝了GnuWin32,可以在bin目錄下看到zcat,更新了PATH,但是我不知道如何在perl腳本中調用zcat。仍然收到錯誤信息'c:/ progra〜1/GnuWin32/bin/zcat'不被識別爲內部或外部命令,可操作程序或批處理文件。 – taiko

2

IO::Zlib->getline將在「行」中讀取。一行被定義爲一行以行尾結尾的數據。 Perl的「\ n」根據操作系統而改變。在Unix(包括Solaris和OS X)上,這是012(換行符)。在Windows上,這是015 012(回車+換行符)。

如果你的文件有Unix換行符,當你在Windows上運行它時,IO::Zlib->getline將尋找Windows換行符。它會嘗試將整個文件讀入內存。通常情況下,您可以通過設置$/,即「輸入記錄分隔符」(又稱「行尾」)爲\015\012來解決此問題,但由於向後兼容性原因,IO :: Zlib(通過Compress::Zlib)不支持$/

幸運的是,所有這些混亂被重寫爲IO :: Compress和IO :: Uncompress。使用IO::Uncompress::Gunzip,你應該已經安裝了它的哪些消耗品壓縮:: Zlib壓縮...

use IO::Uncompress::Gunzip; 

# A block to isolate the local $/ 
{ 
    my $fh = IO::Uncompress::Gunzip->new($file); 

    # the file being read has Unix newlines 
    local $/ = "\012"; 

    # As an added bonus, the object works as a filehandle. 
    while(my $line = <$fh>) { 
     ... 
    } 
} 
+0

儘管這應該起作用,但我最後一次以千兆字節大小的文件爲基準對其進行測試(這是多年前的測試),這比將管道打開到外部'gzip'進程(大概是因爲我在我的回答中提到的原因)要慢得多。即使使用該對象作爲文件句柄,Perl仍然在使用方法調用。 – cjm

+0

@cjm OP沒有問哪個是最快的,他們問爲什麼它不起作用。使用zcat並不能解決換行問題,如果在Windows上使用Unix換行符,''仍然會淹沒整個文件。 '$ /'必須被修改。如果你想要微型性能,我們不知道OP在線上做什麼,使用C程序。如果您想要跨環境兼容性,請使用Perl模塊。由於他們在Solaris和Windows上工作,我認爲跨環境很重要。因人而異。 – Schwern

+0

實際上,使用外部'gzip' * *可以解決換行問題。在Windows上,Pe​​rl默認應用':crlf'圖層,它接受CRLF或LF行尾作爲輸入(將前者轉換爲簡單的LF)。 – cjm