windows - 获取 "format error: can' t 找到带有存档的 EOCD 签名

标签 windows file perl zip

下面的代码工作正常,除了一些 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/

相关文章:

c# - 复制到 Dropbox 文件夹时修改 LastWriteTime

java - 在 JavaFX 中将单个阶段置于窗口的最前面

c++ - 如何在 Windows 中验证用户名和密码?

Linux:删除不包含所有指定单词的文件

perl - 如何使用 Perl 有条件地用单个单词替换一行?

perl - 如何在 Perl XS 中封装库句柄

windows - 将数据从Docker容器持久保存到主机

python - 避免在 Python 中部分写入文件

java - audioInputStream 的 url 似乎为空

perl - 运行单个脚本以仅使用 Perl 核心自动安装缺少的模块的快速方法是什么?