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

为什么不只安装Gzip for Windows(包括zcat)?除了您遇到的内存问题之外,我发现管道gzip传输比使用IO::Zlib. (有几个原因。 $fh->getline是方法调用,而 Perl 的方法调用不是最快的。此外,在gzip外部运行利用了多任务处理,现在多核机器很常见,这一点很明显。)

出于某种原因,GnuWin 提供zcat了一个 shell 脚本,它在 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 回答