Perl IO :: Uncompress :: Unzip

时间:2015-01-14 23:00:44

标签: perl unzip

我正在尝试了解如何使用IO :: Uncompress :: Unzip来解压缩Jar文件。我在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方法导致错误。这里有什么我想念的吗?有没有办法在我获取它之前查看是否有下一个流?

1 个答案:

答案 0 :(得分:0)

我发现了这个问题。

每个目录中都有两个文件:一个是POM,一个是jar(zip)文件。我的外部$dir_fh->read循环遍历目录,它首先拾取jar,然后是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阅读,我在构造函数选项下找到了它:

  
      
  • 透明=&gt; 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,程序可以运行。