Perl使用IO :: Uncompress :: AnyUncompress读取zip文件

时间:2013-04-29 22:01:24

标签: perl unzip

我们正在从我们当前的构建系统(这是一个烂摊子)转变为使用Ant与Ivy的构建系统。我正在清理所有构建文件,并找到jar依赖项。我认为通过检查项目中的jar,找到它们包含的类,然后将这些类与Java代码中的各种import语句进行匹配,我可以更容易地自动化它。

之前我使用过Archive::Tar,但Archive::Zip不是标准的Perl模块。 (我担心的是有人会尝试我的剧本,在半夜打电话告诉我它不起作用。)

我注意到IO::Uncompress::AnyUncompress is a standard module, so I thought I could try IO :: Uncompress :: AnyUncompress or at least IO :: Uncompress :: Unzip`,它也是一个标准模块。

不幸的是,这些模块的文档没有给出任何示例(根据文档,示例是 todo )。

我能够成功打开我的jar并创建一个对象:

 my $zip_obj = IO::Uncompress::AnyUncompress->new ( $zip_file );

现在,我想看看内容。根据文件:

getHeaderInfo

  

用法是

$hdr  = $z->getHeaderInfo();
@hdrs = $z->getHeaderInfo();
  

此方法返回散列引用(在标量上下文中)或列表或散列引用(在数组上下文中),其中包含有关压缩数据流中每个标头字段的信息。

好的,这不是像Archive::TarArchive::Zip这样的对象,并且没有提到解析数据的方法或子例程。我将使用Data::Dumper并查看引用中包含的哈希键。

这是一个简单的测试程序:

#! /usr/bin/env perl
use 5.12.0;
use warnings;

use IO::Uncompress::AnyUncompress;
use Data::Dumper;

my $obj = IO::Uncompress::AnyUncompress->new("testng.jar")

    or die qq(You're an utter failure);

say qq(Dump of \$obj = ) . Dumper $obj;

my @header2 = $obj->getHeaderInfo;
say qq(Dump of \$header = ) . Dumper $headers->[0];

这是我的结果:

Dump of $obj = $VAR1 = bless( \*Symbol::GEN0, 'IO::Uncompress::Unzip' );

Dump of $header = $VAR1 = {
          'UncompressedLength' => 0,
          'Zip64' => 0,
          'MethodName' => 'Stored',
          'Stream' => 0,
          'Time' => 1181224440,
          'MethodID' => 0,
          'CRC32' => 0,
          'HeaderLength' => 43,
          'ExtraFieldRaw' => '¦-  ',
          'ExtraField' => [
                            [
                              '¦-',
                              ''
                            ]
                          ],
          'FingerprintLength' => 4,
          'Type' => 'zip',
          'TrailerLength' => 0,
          'CompressedLength' => 0,
          'Name' => 'META-INF/',
          'Header' => 'PK
     +N¦6                 META-INF/¦-  '
        };

其中一些看起来很有用。但是,我的所有条目都返回''Name'=> 'META-INF /``,因此它看起来不像文件名。

是否可以使用IO::Uncompress::AnyUncompress(甚至IO::Uncompress:Unzip)来阅读存档并查看其内容中的文件。如果是这样,我该如何解析那个标题?

否则,我将不得不使用Archive::Zip并让人们知道他们必须从CPAN下载并在其系统上安装它。

1 个答案:

答案 0 :(得分:4)

存档中的文件在不同的数据流中压缩,因此您需要遍历流以获取单个文件。

use strict;
use warnings;
use IO::Uncompress::Unzip qw(unzip $UnzipError);

my $zipfile = 'zipfile.zip';
my $u = new IO::Uncompress::Unzip $zipfile
    or die "Cannot open $zipfile: $UnzipError";

die "Zipfile has no members"
    if ! defined $u->getHeaderInfo;

for (my $status = 1; $status > 0; $status = $u->nextStream) {
    my $name = $u->getHeaderInfo->{Name};
    warn "Processing member $name\n" ;

    if ($name =~ /\/$/) {
        mkdir $name;
    }
    else {
        unzip $zipfile => $name, Name => $name
            or die "unzip failed: $UnzipError\n";
    }
}