0

Windows で Perl を使用して大きな *.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 ファイルを解析する他の方法はありますか?

4

2 に答える 2

3

Windows 用の Gzip ( を含むzcat)をインストールしないのはなぜですか? あなたが抱えているメモリの問題は別として、からのパイプgzipは を使用するよりも高速であることがわかりましたIO::Zlib。(これにはいくつかの理由があります $fh->getline。. はメソッド呼び出しであり、Perl のメソッド呼び出しは最速ではありません。また、gzip外部での実行はマルチタスクを利用します。これは、マルチコア マシンが一般的になっている現在では顕著です。)

何らかの理由で、GnuWin はzcatシェル スクリプトとして提供しますが、これは Windows では実際には機能しません。ただし、gzip -cd代わりにzcat(Unix プラットフォームでも動作するはずです) を使用できます。

于 2012-09-21T19:47:58.930 に答える
2

IO::Zlib->getline「行」で読み取ります。行は、行の終わりで終わる一連のデータとして定義されます。Perl の「\n」は、オペレーティング システムによって異なります。Unix (Solaris および OS X を含む) では、これは 012 (改行文字) です。Windows では、これは 015 012 (キャリッジ リターン + 改行) です。

ファイルに Unix の改行IO::Zlib->getlineがある場合、Windows で実行すると Windows の改行が検索されます。ファイル全体をメモリに読み込もうとします。$/通常は、「入力レコードセパレーター」別名「行末」を に設定することでこれを修正できます\015\012が、IO::Zlib ( Compress::Zlib$/経由) は下位互換性の理由からサポートしていません。

幸いなことに、この混乱はすべて IO::Compress および IO::Uncompress として書き直されました。IO::Uncompress::Gunzipを使用すると、 Compress::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>) {
        ...
    }
}
于 2012-09-21T22:41:47.453 に答える