下面的代码工作正常,除了一些 zip 文件我收到错误
format error: can't find EOCD signature at C:/LegacyApp/perl/lib/Archive/Zip/Archive.pm line 695 Archive::Zip::Archive::_findEndOfCentralDirectory('Archive::Zip::Archive=HASH(0x375a730)', 'IO::File=GLOB(0x380eb90)') called at C:/LegacyApp/perl/lib/Archive/Zip/Archive.pm line 581 Archive::Zip::Archive::readFromFileHandle('Archive::Zip::Archive=HASH(0x375a730)', 'IO::File=GLOB(0x380eb90)',
Using below piece of code:
use Archive::Zip;
unzip($zipfile,$folder,$out);
sub unzip {
my ($archive, $want, $dir) = @_;
my $zip = Archive::Zip->new($archive);
foreach my $file ($zip->members) {
if (($file->fileName =~ /VERSION\/(.*?).cosipa.xlsx$/i)) {
$zip->extractMember($file,$dir.$file->fileName);
}
if ($file->fileName =~ /VERSION\/(.*?).txt$/i) {
$zip->extractMember($file,$dir.$file->fileName);
}
}
return 1;
}
如果我删除那个特定的 zip 文件,那么它就可以正常工作。但我需要一个解决方案,我应该能够处理这些 zip 文件,如果可能的话,请让我知道代码和 zip 文件中有什么问题。
提前致谢
最佳答案
看来其中一些文件确实存在格式错误。然后你可以捕捉这些失败并处理坏文件(记录名称或删除文件等),否则正常进行。
目前尚不清楚您是否收到警告(程序提示并继续)或错误(发出的 die
正在终止程序),并且需要以不同的方式处理它们。
如果显示的“错误”是异常(程序终止),那么您可以捕获并处理该异常
eval { unzip($zipfile, $folder, $out) };
if ($@) {
say "Error: $@";
# Interrogate. (Is it the expected error or some other?)
# handle it: record the filename for later/delete it/etc ...
}
# control returns here, unless the block above does exit/die/croak/goto
Perl 中处理异常的内置方法( die )是通过 block 形式 eval 。 .† 另请参阅 $@
error variable in perlvar .
如果您的消息只是一条警告,并且程序继续运行,则 eval
无法捕获该消息,因为它仅捕获异常,而不捕获警告。检测这一点的一种方法是安装一个 SIG{__WARN__}
钩子(Hook)并在其中抛出一个 die
,然后与上面相同的 eval
将工作
# Block, so the change to how warnings work is scoped as tight as possible
HANDLE_ZIP: {
local $SIG{__WARN__} = sub {
die $_[0] if $_[0] =~ /^\s*format error:/; # raise exception, or
warn $_[0]; # re-emit the warning
};
eval { unzip($zipfile, $folder, $out) };
if ($@) {
# same as above...
}
};
现在,如果 unzip
发出警告,则不会打印警告,而是调用分配给 $SIG{__WARN__}
的引用的 sub。然后,如果警告消息与该正则表达式匹配,则会抛出一个 die
以及该消息。由于这是在 eval
内部触发的,因此会进行处理,如前面的代码示例所示。请参阅%SIG
in perlvar .
另一种方法是简单地在 $SIG{__WARN__}
中针对任何警告引发异常(仅在该 block 内!),然后处理 eval
中的所有详细信息的处理程序。
请注意local在这一切中很重要,因此我们不会改变警告在所有代码中的工作方式,而只在这个 block 中改变。
这应该可以正常工作,但请研究链接的文档。
† 直接处理 $@
曾经存在微妙的陷阱(v5.14 之前)。虽然这个问题已经解决,但所有这些确实是低级的,考虑使用模块可能是一个好主意。这将包装 eval
+$@
以便更容易理解,也许也更容易正确使用。
关于windows - 获取 "format error: can' t 找到带有存档的 EOCD 签名,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54396297/