Почему ZipInputStream не может прочитать выходные данные ZipOutputStream? - PullRequest
6 голосов
/ 13 ноября 2010

Я застрял с этим тестом джунта:

public void test() throws Exception {
    ByteArrayOutputStream out = new ByteArrayOutputStream();
    ZipOutputStream zipOut = new ZipOutputStream( out );
    zipOut.putNextEntry( new ZipEntry( "file" ) );
    zipOut.write( (new byte[] { 0x01, 0x02, 0x03 }) );
    zipOut.closeEntry();
    zipOut.close();

    ZipInputStream zipIn = new ZipInputStream( new ByteArrayInputStream( out.toByteArray() ) );
    ZipEntry entry = zipIn.getNextEntry();
    assertNotNull( entry );
    assertEquals( "file", entry.getName() );
    assertEquals( 3, entry.getSize() );
}

Я пишу файл с именем «file» и содержимым трех байтов в ZipOutputStream. Затем я пытаюсь прочитать созданные данные с помощью ZipInputStream, но последнее утверждение не удается, потому что entry.getSize() равно -1, а не 3, как и ожидалось.

Что я здесь не так делаю? Что мне нужно изменить, чтобы восстановить содержимое «файла»? Я думаю, я сначала должен знать длину, чтобы иметь возможность читать данные из потока?

Ответы [ 5 ]

3 голосов
/ 13 ноября 2010

Вы действительно должны прочитать содержимое записи, тогда entry.getSize() вернет правильный размер.

Для чтения записи используйте:

    byte[] buf = new byte[1024];
    int len;
    while ((len = zipIn.read(buf)) > 0) {
        // use data;
    }
1 голос
/ 13 ноября 2010

Чтение API doc для ZipEntry.Там написано "если известно".Вы можете прочитать содержимое, используя следующее (он просто печатает размер zipentry, изменяет данные обработки соответствующим образом):

ZipEntry entry = zipIn.getNextEntry();
int BUFSIZE = 1024;
byte [] buffer = new byte[BUFSIZE];
int read = 0;
int total = 0;
while( (read = zipIn.read(buffer, 0, BUFSIZE)) >0 ) { 
  total += read;
  // what do you want to do with the data read? Do it here
}   
System.err.println("Total: " + total);
1 голос
/ 13 ноября 2010

Я нашел ответ сам: entry не содержит правильный размер, но с каждым zipIn.getNextEntry() вы получаете свежий поток для чтения содержимого вашей записи. Так что просто прочитайте поток до конца, и у вас есть данные вашей записи.

В моем тесте junit последняя строка может выглядеть так:

byte[] restoredContent = new byte[ 10 ];
assertEquals( 3, zipIn.read( restoredContent ) );

Теперь все отлично работает.

0 голосов
/ 25 апреля 2017

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

Следующий фрагмент привел к исключению java.lang.NegativeArraySizeException.

zipEntry = zipInputStream.getNextEntry();
byte[] bytes = new byte[(int) zipEntry.getSize()];

Быстрое решение - использовать Apache commons-io IOUtils для чтения всех байтов текущей записи.

zipEntry = zipInputStream.getNextEntry();
byte[] bytes = org.apache.commons.io.IOUtils.toByteArray(zipInputStream);

Надеюсь, это кому-нибудь пригодится.

0 голосов
/ 14 июня 2011

Та же проблема здесь!

ZipInputStream не может прочитать выходные данные ZipOutputStream;

новый ZipFile (файл) завершается с ошибкой

нет возможных объяснений!

Программа просмотра архивов прекрасно открывает zip-файл!

РЕШЕНИЕ: Э-э ... это ведь не zip-файл ... это был tar-файл с именем 'folder.zip'. Просмотрщик архивов был достаточно умен ...

Для тех, кто с этой проблемой: Дважды проверьте !!!

...