Perl6:逐行读取大型压缩文件

内容来源于 Stack Overflow,并遵循CC BY-SA 3.0许可协议进行翻译与使用

  • 回答 (2)
  • 关注 (0)
  • 查看 (188)

我试图在Perl6中逐行读取gz文件,但是,我被阻止了:

  1. 如何在Perl6中逐行读取gz文件,然而,这个方法,读取所有东西:out使用太多的RAM可用,除非是非常小的文件。
  2. 我不明白如何使用Perl6 Compress::Zlib来逐行获取所有内容,尽管我在他们的github上打开了一个问题https://github.com/retupmoca/P6-Compress-Zlib/issues/17
  3. 我正在尝试Perl5 Compress::Zlib来翻译这段代码,它在Perl5中完美运行:

use Compress::Zlib; my $file = "data.txt.gz"; my $gz = gzopen($file, "rb") or die "Error reading $file: $gzerrno"; while ($gz->gzreadline($_) > 0) { # Process the line read in $_ } die "Error reading $file: $gzerrno" if $gzerrno != Z_STREAM_END ; $gz->gzclose() ;

Inline::Perl5在Perl6中使用这样的东西:

use Compress::Zlib:from<Perl5>;
my $file = 'chrMT.1.vcf.gz';
my $gz = Compress::Zlib::new(gzopen($file, 'r');
while ($gz.gzreadline($_) > 0) {
  print $_;
}
$gz.gzclose();

但我看不出如何翻译这个:(

  1. 我很困惑Lib :: Archive示例https://github.com/frithnanth/perl6-Archive-Libarchive/blob/master/examples/readfile.p6我看不到我怎么能在这里获得类似第3项的内容
  2. 应该有类似的东西

for $file.IO.lines(gz) -> $line { 或类似Perl6中的东西,如果它存在,我找不到它。

如何在不读取Perl6内存中的所有内容的情况下逐行读取大文件?

提问于
用户回答回答于

尝试解决方案#2

一个快速未经测试的猜测,如何使用P6的Compress :: Zlib基于其README(并知道P6):

use Compress::Zlib ;

my $file   = "data.txt.gz" ;
my $handle = try open $file or die "Error reading $file: $!" ;
my $zwrap  = zwrap($handle) ;

for $zwrap.lines {
    # Process the line read in $_
}

CATCH { default { die "Error reading $file: $_" } }

$handle.close ;

请评论它是否有效。如果它工作,它是否足够快你的大文件。如果它不起作用我会花更多的时间; 解释它是否有效; 如果它工作但速度不够快,那就专注于加速它和/或P5选项。

用户回答回答于

这是现在的解决方法。

curent目录中创建一个包装器模块,例如./MyZlibWrapper.pm

package MyZlibWrapper;
use strict;
use warnings;
use Compress::Zlib ();
use Exporter qw(import);

our @EXPORT = qw(gzopen);
our $VERSION = 0.01;
my $private_open_fh;

sub gzopen {
    my ( $fn, $mode ) = @_;
    my $gz = Compress::Zlib::gzopen( $fn, $mode );
    $private_open_fh->{gz} = $gz; 
    return bless $private_open_fh, __PACKAGE__;
}

sub gzreadline {
    my ( $self ) = @_;
    my $line = "";
    my $res = $self->{gz}->gzreadline($line);
    return [$res, $line];
}

sub gzclose {
    my ( $self ) = @_;
    $self->{gz}->gzclose();
}

1;

然后Inline::Perl5在这个包装器模块上使用而不是Compress::Zlib。例如./p.p6

use v6;
use Inline::Perl5;
my $p5 = Inline::Perl5.new;

$p5.run('use lib ".";');
$p5.use('MyZlibWrapper');
#use MyZlibWrapper:from<Perl5>;
my $file = 'data.txt.gz';
my $mode = 'rb';
my $gz = $p5.call('gzopen', $file, $mode);
loop {
    my ($res, $line) = $gz.gzreadline();
    last if $res == 0;
    print $line;
}
$gz.gzclose();

扫码关注云+社区

领取腾讯云代金券

年度创作总结 领取年终奖励