Perl IO::Uncompress::Unzip



我正在尝试了解如何使用IO::Uncompress::Unzip来解压缩Jar文件。我在罐子打印中得到了文件的名称,但是我收到错误:

Can't call method "reset" on an undefined value at ../IO/Uncompress/Base.pm line 986.

在我读完最后一个条目之后。这是我的模块:

sub modify_artifact {
    my %parameters = @_;
    my @required_parameters = qw( version directory );
    for my $parameter ( @required_parameters ) {
        if ( not exists $parameters{$parameter} ) {
            die qq(ERROR: Missing required parameter "$parameter");
        }
    }
    my $directory = $parameters{directory};
    my $dir_fh = IO::Dir->new( $parameters{directory} ) or
        die qq(ERROR: Cannot open directory "$parameters{directory} for reading.);
    while ( my $file_name  = $dir_fh->read ) {
        next if $file_name =~ /^./;             #Hidden and "." and ".."
        my $full_file_name = File::Spec->join( $directory, $file_name );
        my $archive_fh = IO::Uncompress::Unzip->new( $full_file_name ) or
            die qq(ERROR: Cannot open file "$full_file_name" for reading.);
        while ( my $status = $archive_fh->nextStream ) {
            last unless $status > 0;
            say $archive_fh->getHeaderInfo->{Name};   # Print out file or directory
        }
    }
}

say行适用于存档中的每个条目,但是在尝试读取下一个流时出现失败:

META-INF/MANIFEST.MF
META-INF/maven/
META-INF/maven/com.vegicorp/
META-INF/maven/com.vegicorp/services/
META-INF/maven/com.vegicorp/services/pom.properties
META-INF/maven/com.vegicorp/services/pom.xml
com/
com/vegicorp/
com/vegicorp/services/
com/vegicorp/services/filter/
com/vegicorp/services/filter/impl/
com/vegicorp/services/generators/
com/vegicorp/services/filter/impl/DescInfoFilter.class
com/vegicorp/services/filter/impl/RequestFilterAals.class
com/vegicorp/services/generators/OutputGenerator$1.class
com/vegicorp/services/generators/OutputGenerator.class  <- Last entry in archive
Can't call method "reset" on an undefined value at ../IO/Uncompress/Base.pm line 986.

我也尝试了示例中所示的for循环:

sub modify_artifact {
    my %parameters = @_;
    my @required_parameters = qw( version directory );
    for my $parameter ( @required_parameters ) {
        if ( not exists $parameters{$parameter} ) {
            die qq(ERROR: Missing required parameter "$parameter");
        }
    }
    my $directory = $parameters{directory};
    my $dir_fh = IO::Dir->new( $parameters{directory} ) or
        die qq(ERROR: Cannot open directory "$parameters{directory} for reading.);
    while ( my $file_name  = $dir_fh->read ) {
        next if $file_name =~ /^./;             #Hidden and "." and ".."
        my $full_file_name = File::Spec->join( $directory, $file_name );
        my $archive_fh = IO::Uncompress::Unzip->new( $full_file_name ) or
            die qq(ERROR: Cannot open file "$full_file_name" for reading.);
        my $status;
        for ($status = 1; $status > 0; $status = $archive_fh->nextStream()) {
            say $archive_fh->getHeaderInfo->{Name};
            last if $status < 0;
        }
    }
}

但我遇到了同样的问题。似乎nextStream方法导致了错误。我在这里缺少什么吗?有没有办法在我获取之前查看是否有下一个流?

我发现了这个问题。

每个目录中有两个文件:一个是 POM,一个是 jar (zip) 文件。我的外部$dir_fh->read循环遍历目录,它首先拾取罐子,然后是POM。

第一次通过,内部循环首先获取jar文件,用IO::Uncompress::Unzip打开它。内部循环没有问题,并按预期退出。

外部循环现在获取 POM 文件,并将其传递给IO::Uncompress::Unzip打开。 IO::Uncompress::Unzip->new返回零状态 - 即使这不是 zip 文件。但是,$archive_fh->nextStream呱呱叫,因为没有下一个流要获取。

由于我没有任何迹象表明新文件已打开,因此我从未检测到 POM 正在打开并且对 nextStream 的使用导致我的程序呱呱叫。

因此,IO::Uncompress:Unzip->new打开未压缩的文件,就好像它们是 zip 文件一样,并返回有效的文件句柄。

通读Perldoc,我在构造函数选项下找到了这个:

  • 透明 => 0|1
     
    如果设置了此选项并且输入文件/缓冲区不是压缩数据,则模块将允许读取它。 此外,如果输入文件/缓冲区确实包含压缩数据,并且紧随其后的是非压缩数据,则设置此选项将使该模块将整个文件/缓冲区视为单个数据流。
     
    此选项默认为 1。

好的,默认情况下,IO::Uncompress::Unzip会打开非 zip 文件进行读取。如果我想结束此行为,我需要这样做:

my $archive_fh = IO::Uncompress::Unzip->new( 
    $full_file_name, 
    Transparent => 0,
) or die qq(ERROR: Cannot open file "$full_file_name" for reading.);

这不会以 ZIP 形式打开我的 POM,并且该程序可以工作。

最新更新