Archive::Zip 无法在 Perl 中创建 Zip 对象

Posted

技术标签:

【中文标题】Archive::Zip 无法在 Perl 中创建 Zip 对象【英文标题】:Archive::Zip Couldn't create Zip object in Perl 【发布时间】:2014-03-21 09:27:10 【问题描述】:

我是 Perl 语言编程的新手。我从 Cpan 官方网站 (https://metacpan.org/pod/Net::FTP::RetrHandle) 剪切并粘贴了一个简短的示例,该示例在 Zip 文件中列出了成员名称,而无需下载整个内容。请注意,我将第一行从“#!/usr/bin/perl”更改为“#!/root/localperl/bin/perl”,因为我想使用最新的 Perl 版本 5.18.2。

#!/root/localperl/bin/perl

    use warnings;
    use strict;

    use Net::FTP;
    use Net::FTP::AutoReconnect;
    use Net::FTP::RetrHandle;
    use Archive::Zip;

    my $ftp = Net::FTP::AutoReconnect->new("ftp.info-zip.com", Debug => $ENVDEBUG) 
        or die "connect error\n";
    $ftp->login('anonymous','example@example.com')
        or die "login error\n";
    $ftp->cwd('/pub/infozip/unix/linux')
        or die "cwd error\n";
    my $fh = Net::FTP::RetrHandle->new($ftp,'unz551x-glibc.zip')
        or die "Couldn't get handle to remote file\n";
    my $zip = Archive::Zip->new($fh)
        or die "Couldn't create Zip object\n";
    foreach my $fn ($zip->memberNames())
    
      print "unz551-glibc.zip: $fn\n";
    

我 gedit ".bash_profile",并添加以下环境变量以供 Perl 特定版本使用:

PERL_BIN=$HOME/localperl/bin
PERL_LIB=$HOME/localperl/lib/5.18.2

export PATH=$PERL_BIN:$PERL_LIB:$PATH

[root@cspp ~]# echo $PATH

/root/localperl/bin:/root/localperl/lib/5.18.2:/usr/lib64/qt-3.3/bin:/usr/local/sbin:/usr/sbin:/sbin:/usr/本地/bin:/usr/bin:/bin:/root/bin:/root/bin

我们可以通过运行以下命令来检查当前的 Perl 版本:

[root@cspp ~]# perl -v

这是为 x86_64-linux 构建的 perl 5,版本 18,subversion 2 (v5.18.2)

版权所有 1987-2013,拉里·沃尔

Perl 只能根据艺术许可或 GNU 通用公共许可证,可在 Perl 5 源工具包中找到。

Perl 的完整文档,包括常见问题列表,应该在 本系统使用“man perl”或“perldoc perl”。如果您有权访问 互联网,将您的浏览器指向 http://www.perl.org/,Perl 主页。

当我执行上述代码sn-ps时,它会抛出以下错误:

[root@cspp ~]# perl zipdown.pl

IO 错误:读取失败:在 /root/localperl/lib/5.18.2/Archive/Zip/Archive.pm 第 705 行。 Archive::Zip::Archive::_findEndOfCentralDirectory('Archive::Zip::Archive=HASH(0x1d55618)', 'Net::FTP::RetrHandle=HASH(0x1d55528)') 调用于 /root/localperl/lib/5.18.2/Archive/Zip/Archive.pm 第 607 行 Archive::Zip::Archive::readFromFileHandle('Archive::Zip::Archive=HASH(0x1d55618)', 'Net::FTP::RetrHandle=HASH(0x1d55528)', 'Net::FTP::RetrHandle=HASH(0x1d55528)') 调用于 /root/localperl/lib/5.18.2/Archive/Zip/Archive.pm 第 574 行 Archive::Zip::Archive::read('Archive::Zip::Archive=HASH(0x1d55618)', 'Net::FTP::RetrHandle=HASH(0x1d55528)') 调用于 /root/localperl/lib/5.18.2/Archive/Zip/Archive.pm 第 59 行 Archive::Zip::Archive::new('Archive::Zip::Archive', 'Net::FTP::RetrHandle=HASH(0x1d55528)') 调用于 /root/localperl/lib/5.18.2/Archive/Zip.pm 第 284 行 存档::Zip::new('存档::Zip', 'Net::FTP::RetrHandle=HASH(0x1d55528)') 在 zipdown.pl 第 19 行调用 无法创建 Zip 对象

第19行出现“Couldn't create Zip object”的错误。我认为这种错误不应该是简单的官方源代码本身造成的。所以我提供了一些相关的路径和文件供大家参考:

/root/localperl/lib/5.18.2/Archive/(Extract.pm, Tar.pm, Zip.pm) /root/localperl/lib/5.18.2/Archive/Tar/(Constant.pm, File.pm) /root/localperl/lib/5.18.2/Archive/Zip/(Archive.pm, BufferedFileHandle.pm, DirectoryMember.pm, FAQ.pod, FileMember.pm, Member.pm、MemberRead.pm、MockFileHandle.pm、NewFileMember.pm、 StringMember.pm, Tree.pm, ZipFileMember.pm)

/root/localperl/lib/5.18.2/Net/(Cmd.pm, Config.pm, Domain.pm, FTP.pm, hostent.pm、libnetFAQ.pod、netent.pm、Netrc.pm、NNTP.pm、Ping.pm、 POP3.pm、protoent.pm、servent.pm、SMTP.pm、Time.pm) /root/localperl/lib/5.18.2/Net/FTP/(A.pm, AutoReconnect.pm, dataconn.pm, E.pm, I.pm, L.pm, RetrHandle.pm)

值得一提的是,Perl 安装程序默认无法安装 Zip 模块。因此,我使用“cpan”环境独立安装如下:

root# cpan
cpan> install Archive::Zip
cpan> quit
root#

另外,为了使用 Net::FTP::AutoReconnect 和 Net::FTP::RetrHandle 模块,我下载了 perl-Net-FTP-AutoReconnect-0.3-3.el6.noarch.rpm 和 perl-Net -FTP-RetrHandle-0.2-3.el6.noarch.rpm 分别从http://pkgs.org/centos-6/epel-i386/perl-Net-FTP-AutoReconnect-0.3-3.el6.noarch.rpm.html和http://pkgs.org/centos-6/epel-i386/perl-Net-FTP-RetrHandle-0.2-3.el6.noarch.rpm.html链接,一一安装:

rpm -ivh perl-Net-FTP-AutoReconnect-0.3-3.el6.noarch.rpm
rpm -ivh perl-Net-FTP-RetrHandle-0.2-3.el6.noarch.rpm

据我所知,我花了一整天的时间尝试所有可能的解决方案。我现在无事可做,只能向来自 SO 的 Perl 专家寻求帮助。非常感谢您!

【问题讨论】:

文件是否存在?您可以使用常规 FTP 客户端下载该文件吗? @Colin Pickard:感谢您关注我的问题。是的。 ftp.info-zip.com/pub/infozip/unix/linux/unz551x-glibc.zip 肯定是 FTP 主机。 【参考方案1】:

首先,搞清楚如何设置 perl + 库的本地副本做得很好。但是最好不要使用 perl 进行学习。

其次,尽管 CPAN 是“官方的”,但您在其上找到的软件包是由很多人编写的,而且代码质量参差不齐。 Net::FTP::RetrHandle 的版本是 0.2,并且可以追溯到 2006 年。这并不意味着它是糟糕的代码,只是它没有被大量使用。

我尝试了这个例子,但和你一样失败了。

然后我在末尾注释掉了 Archive::Zip 代码,只是使用文件句柄从 FTP 服务器读取数据并将其保存到文件中。该文件似乎是一个有效的 ZIP 存档,所以我们知道基础知识很好。

然后我尝试为 Archive::Zip 代码提供一个普通的文件句柄来使用。那很好。

所以 - 这是两者之间的一些互动。查看 Archive::Zip 源代码,当它从文件末尾向后搜索后尝试读取时发生错误。所以 - 我查看了 Net::FTP::RetrHandle 模块中的 seek 子例程。在那里我注意到你可以设置一个调试环境变量,我这样做了。

export DEBUG=1
perl ftp_fh_test.pl
...
Net::FTP=GLOB(0x2e99ce8)<<< 250 Connected to /dsa0/infozip/pub/infozip/unix/linux.
Net::FTP=GLOB(0x2e99ce8)>>> PORT 192,168,1,43,226,125
Net::FTP=GLOB(0x2e99ce8)<<< 200 Port 226.125 at Host 80.229.41.160 accepted.
Net::FTP=GLOB(0x2e99ce8)>>> REST 155293
Net::FTP=GLOB(0x2e99ce8)<<< 500 I never heard of the REST command.  Try HELP.
IO error: read failed...

所以 - FTP 服务器无法识别“REST”命令,因此您无法通过该服务器进行搜索。尝试不同的 FTP 服务器。

您可能还喜欢 perlbrew 和 local::lib 作为开发设置的一部分。对于设置本地 perl 环境非常有用。

【讨论】:

感谢您抽出宝贵的时间为我的问题调试失败原因。 RetrHandle.pm(2006 年 9 月 27 日)和 AutoReconnect.pm(2009 年)都是非常古老的模块,由 Scott Gifford 编写。我的最终目标是通过 FTP 从 TAR 存档 (>2GB) 中提取单个文件,而无需下载整个文件。你提到了 perlbrew 和 local::lib,他们为我做了这种事情吗? 不,perlbrew 和 local::lib 将帮助您管理您的 perl 代码。我担心你的任务会很繁琐,因为 FTP 并不是为此而设计的,而且有很多不同的服务器支持很多不同的命令集。【参考方案2】:

我怀疑您只下载了 Perl 本身,但没有升级 Perl 模块。

它(可能)适用于 PuePerl (PP) 模块,但适用于使用 XS(C 代码)的模块。

解决方案是也下载模块。

http://www.cpan.org/misc/how-to-mirror.html

最简单的:

/usr/bin/rsync -av --delete cpan-rsync.perl.org::CPAN /project/CPAN/

更好:

How can I use CPAN as a non-root user?

wget -O- http://cpanmin.us | perl - -l ~/perl5 App::cpanminus local::lib
eval `perl -I ~/perl5/lib/perl5 -Mlocal::lib`
echo 'eval `perl -I ~/perl5/lib/perl5 -Mlocal::lib`' >> ~/.profile

问候,

【讨论】:

非常感谢。在我花时间测试您的方法之前,我想问您一个关于“如何设置 Perl 开发环境?”的问题。我这样做: wget cpan.org/src/5.0/perl-5.18.2.tar.gz tar -xzf perl-5.18.2.tar.gz cd perl-5.18.2 ./Configure -des -Dprefix=$HOME/localperl make make test make install

以上是关于Archive::Zip 无法在 Perl 中创建 Zip 对象的主要内容,如果未能解决你的问题,请参考以下文章

Perl Archive::zip -- 文件没有被添加

如何使用 perl Archive::Zip 将文件添加到存档中?

Perl Archive::Zip 创建不必要的文件夹

你如何在 Perl 中创建对象?

Perl - 如何使用在另一个 Perl 脚本的模块中创建的进程句柄

如何在 Perl 中创建或测试 NaN 或无穷大?