Perl - 在Windows中解析巨大的* .gz文件

时间:2012-09-21 19:17:16

标签: perl parsing gz

我正在尝试使用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)。有没有其他方法来解析big * .gz文件?

2 个答案:

答案 0 :(得分:2)

为什么不安装Gzip for Windows(包括zcat)?除了您遇到的内存问题,我发现来自gzip的管道比使用IO::Zlib更快。 (有几个原因。$fh->getline是一个方法调用,而Perl的方法调用并不是最快的。另外,在外部运行gzip会利用多任务处理,现在可以注意到多任务核心机器很常见。)

出于某种原因,GnuWin提供zcat作为shell脚本,在Windows下无法正常工作。但是你可以使用gzip -cd而不是zcat(这也适用于Unix平台)。

答案 1 :(得分: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>) {
        ...
    }
}