我正在尝试使用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文件?
答案 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>) {
...
}
}