我正在尝试了解如何使用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
方法导致错误。这里有什么我想念的吗?有没有办法在我获取它之前查看是否有下一个流?
答案 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,程序可以运行。