ZipFile выдает ошибку, но ZipInputStream может распаковать архив

У меня странное поведение с java.util.zip.*

У меня есть zip-файл, и при распаковке происходит следующее:

ZipFile zipfile = new ZipFile(file, ZipFile.OPEN_READ);

Это точное сообщение об ошибке

java.util.zip.ZipException: error in opening zip file
at java.util.zip.ZipFile.open(Native Method)
at java.util.zip.ZipFile.<init>(ZipFile.java:127)
at java.util.zip.ZipFile.<init>(ZipFile.java:143)
at com.basware.ExtractZip.unpack(ExtractZip.java:27)
at com.basware.ExtractZip.main(ExtractZip.java:17)

Но если я использую следующий код, он сможет открыть архив без ошибок.

try {
     BufferedOutputStream dest = null;       
     File file = new File("File_Path");        
     FileInputStream fis = new FileInputStream(file);
     ZipInputStream zis = new ZipInputStream(new BufferedInputStream(fis));
     ZipEntry entry;
     while((entry = zis.getNextEntry()) != null) {
        System.out.println("Extracting: " +entry);
        int count;
        byte data[] = new byte[BUFFER];
        // write the files to the disk
        FileOutputStream fos = new 
      FileOutputStream(entry.getName());
        dest = new 
          BufferedOutputStream(fos, BUFFER);
        while ((count = zis.read(data, 0, BUFFER)) 
          != -1) {
           dest.write(data, 0, count);
        }
        dest.flush();
        dest.close();
     }
     zis.close();

Обратите внимание, что файлы сжаты с помощью WinZIP.

Мой вопрос в том, что ZipFile и ZipInputStream почти одинаковы, почему ZipFile дает исключение и почему он не может выполнить распаковку.

РЕДАКТИРОВАТЬ: проблема заключается в том, что если я заархивирую файл с помощью инструмента WinZip, а затем распаковаю его с помощью указанной программы, он работает нормально. Но эта проблема особенно возникает для архивов, поступающих из внешнего источника (внешний источник утверждает, что они используют WinZip). On кроме того, если я открою тот же самый архив (внешний) с помощью инструмента WinZip, он покажет и распаковает файлы. Но этот специальный код JAVA (ZipFile) вообще не работает.

РЕДАКТИРОВАТЬ: я не могу понять, почему собственный код Java не работает для моих ZIP-архивов, но сжатие apache решило мою проблему. У меня это работает, как предложил Ян Робертс.


person C4CodeE4Exe    schedule 10.12.2012    source источник


Ответы (2)


ZipFile пытается разобрать «центральный каталог» в конце zip, чтобы создать структуру данных, которая позволит вам получить доступ к отдельным записям по имени. ZipInputStream этого не делает, он просматривает только локальный заголовок каждой записи при чтении файла сверху вниз. Таким образом, похоже, что в вашем файле есть хорошие записи, но по какой-то причине поврежден центральный каталог.

Существует ряд возможностей, например проблемы с кодированием символов, отличных от ASCII, в имена записей или если в архиве более 64 000 записей. Я бы попробовал commons-compress реализацию ZipFile - даже если она не работает, она должна дать вам более конкретное сообщение об ошибке, чем "что-то не так", которое вы получаете от java.util.zip.

person Ian Roberts    schedule 10.12.2012
comment
@ C4CodeE4Exe, это одна из проблем частично встроенной реализации zip в Java, ее сообщения об ошибках не очень полезны ... Я добавил еще несколько идей. - person Ian Roberts; 10.12.2012
comment
Я попытался использовать org.apache.commons.compress.archivers.zip.ZipFile, и он может показать мне записи, а не ошибки. Но некоторые исключения: нет метода getName, записи были переименованы в getEntries, getEntries и getEntry. возвращайте экземпляры org.apache.commons.compress.archivers.zip.ZipArchiveEntry, close может вызывать исключение IOException. - person C4CodeE4Exe; 10.12.2012

В дополнение к ответу Яна Роберта, если Java 7 является вариантом, вы можете обойти старые библиотеки java.util.zip в пользу использования поставщик файловой системы ZIP.

person Tom G    schedule 10.12.2012
comment
Извините. Мы не используем Java 7. - person C4CodeE4Exe; 11.12.2012