Получение "ошибки формата: не удается найти подпись EOCD" с архивами - PullRequest
0 голосов
/ 28 января 2019

Код ниже работает нормально, за исключением того, что для некоторых 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)',

Используя приведенный ниже фрагмент кода:

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-файлах.

Заранее спасибо

1 Ответ

0 голосов
/ 28 января 2019

Кажется, что некоторые из этих файлов действительно имеют ошибки формата.Затем вы можете отследить эти сбои и обработать неверные файлы (имена записей или удалить файлы и т. Д.) И в противном случае продолжить работу в обычном режиме.

Если отображаемая вами «ошибка» является исключением (программа умирает), то вы можетеловите и обрабатывайте это

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 ...
}

Встроенный способ обработки «исключений» в Perl - который просто die - это через (блочную форму) eval , Также см. переменную ошибки $@ в perlvar .

Если ваше сообщение является простым предупреждением, а программа продолжается, то eval не может перехватитьтот.Один из способов обнаружить это - установить SIG{__WARN__} хук и в него добавить 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...
    }
};

Теперь, если из-за * появляется предупреждение1024 *, вместо печати вызывается сабвуфер со ссылкой, присвоенной $SIG{__WARN__}.Затем, если сообщение предупреждения соответствует этому регулярному выражению, вместо этого выдается die с этим сообщением.Поскольку это происходит внутри eval, оно обрабатывается, как указано выше.См. %SIG в perlvar .

Другой способ - просто вызвать исключение в $SIG{__WARN__} для любого предупреждения (только внутри этого блока!), А затем обработать все детали в eval обработчик.Обратите внимание, что local имеет решающее значение, так что мы не меняем принцип работы предупреждений по всему коду.

Это набросок (даже если он должен работать в том виде, в котором он стоит).Пожалуйста, изучите связанные документы.


Раньше были тонкие ловушки с обработкой $@ напрямую (до v5.14).Несмотря на то, что это было решено, все это на самом деле низкоуровневое, и это может быть хорошей идеей, чтобы рассмотреть возможность использования модуля вместо этого.Это обернуло бы eval + $@ для облегчения пищеварения и, возможно, для более правильного использования.

Пожалуйста, ищите альтернативы, но имейте в виду, что мода менялась и что многие приходили и уходили годами.Вот одно недавнее обсуждение некоторых опций.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...