Чтение из ZipInputStream в ByteArrayOutputStream

Многие объяснения уже присутствуют, чтобы объяснить, как это происходит и как это исправить, но вы также должны следовать рекомендациям, чтобы избежать NullPointerException вообще.

См. также: A хороший список лучших практик

Я бы добавил, очень важно, хорошо использовать модификатор final. Использование "окончательной" модификатор, когда это применимо в Java

Сводка:

  1. Используйте модификатор final для обеспечения хорошей инициализации.
  2. Избегайте возврата null в методы, например, при возврате пустых коллекций.
  3. Использовать аннотации @NotNull и @Nullable
  4. Быстрое завершение работы и использование утверждений, чтобы избежать распространения нулевых объектов через все приложение, когда они не должен быть пустым.
  5. Сначала используйте значения с известным объектом: if("knownObject".equals(unknownObject)
  6. Предпочитают valueOf() поверх toString ().
  7. Используйте null safe StringUtils StringUtils.isEmpty(null).

18
задан joce 9 March 2013 в 02:38
поделиться

9 ответов

Ваш цикл выглядит допустимым - что следующее кодирует (только на своем собственном) возврат?

zipStream.read(tempBuffer)

, если это возвращается-1, тогда zipStream закрывается, прежде чем Вы получите его, и все ставки выключены. Пора использовать Ваш отладчик и удостовериться, что передается Вам, на самом деле допустимо.

при вызове getNextEntry () он возвращает значение и является данными в значимой записи (т.е. getCompressedSize () возвращают допустимое значение)? ЕСЛИ Вы просто читаете zip-файл, который не имеет считанных вперед записей zip встроенными, то ZipInputStream не собирается работать на Вас.

Некоторые полезные лакомые кусочки о формате Zip:

Каждый файл, встроенный в zip-файл, имеет заголовок. Этот заголовок может содержать полезную информацию (такую как сжатая длина потока, это смещается в файле, CRC) - или это может содержать некоторые волшебные значения, которые в основном говорят, что 'Информация не находится в потоковом заголовке, необходимо проверить заключительную часть сообщения Zip'.

Каждый zip-файл тогда имеет таблицу, которая присоединяется до конца файла, который содержит все записи zip, наряду с реальными данными. Таблица в конце обязательна, и значения в нем должны быть корректными. Напротив, значения, встроенные в поток, не должны быть обеспечены.

при использовании ZipFile он читает таблицу в конце zip. Если Вы используете ZipInputStream, я подозреваю, что getNextEntry () пытается использовать записи, встроенные в поток. Если те значения не определяются, то ZipInputStream понятия не имеет, какой длины поток мог бы быть. Расширять алгоритм сам завершающийся (Вы на самом деле не должны знать несжатую длину потока вывода, чтобы полностью восстановить вывод), но возможно, что версия Java этого читателя не обрабатывает эту ситуацию очень хорошо.

я скажу, что довольно необычно иметь сервлет, возвращая ZipInputStream (намного более распространено получить inflatorInputStream, если Вы собираетесь быть получением сжатое содержание.

7
ответ дан 30 November 2019 в 08:33
поделиться

Вы, вероятно, пытались читать из FileInputStream как это:

ZipInputStream in = new ZipInputStream(new FileInputStream(...));

Этот работа won’t, так как архив zip может содержать несколько файлов и необходимо определить который файл читать.

Вы могли использовать java.util.zip. ZipFile и библиотека такой как IOUtils от Apache Commons IO или ByteStreams от Гуавы , которые помогают Вам в копировании потока.

Пример:

ByteArrayOutputStream out = new ByteArrayOutputStream();
try (ZipFile zipFile = new ZipFile("foo.zip")) {
    ZipEntry zipEntry = zipFile.getEntry("fileInTheZip.txt");

    try (InputStream in = zipFile.getInputStream(zipEntry)) {
        IOUtils.copy(in, out);
    }
}
7
ответ дан 30 November 2019 в 08:33
поделиться

Я использовал бы IOUtils от свободного городского населения io проект.

IOUtils.copy(zipStream, byteArrayOutputStream);
4
ответ дан 30 November 2019 в 08:33
поделиться

Вы могли реализовать свою собственную обертку вокруг ZipInputStream, который игнорирует близко (), и передайте это в стороннюю библиотеку.

thirdPartyLib.handleZipData(new CloseIgnoringInputStream(zipStream));


class CloseIgnoringInputStream extends InputStream
{
    private ZipInputStream stream;

    public CloseIgnoringInputStream(ZipInputStream inStream)
    {
        stream = inStream;
    }

    public int read() throws IOException {
        return stream.read();
    }

    public void close()
    {
        //ignore
    }

    public void reallyClose() throws IOException
    {
        stream.close();
    }
}
3
ответ дан 30 November 2019 в 08:33
поделиться

Я назвал бы getNextEntry () на ZipInputStream, пока это не при записи, которую Вы хотите (используйте ZipEntry.getName () и т.д.). Вызов getNextEntry () усовершенствует "курсор" к началу записи, которую это возвращает. Затем используйте ZipEntry.getSize () для определения, сколько байтов необходимо считать использование zipInputStream.read ().

1
ответ дан 30 November 2019 в 08:33
поделиться

Неясно, как Вы получили zipStream. Это должно работать, когда Вы получаете его как это:

  zipStream = zipFile.getInputStream(zipEntry)
0
ответ дан 30 November 2019 в 08:33
поделиться

t неясен, как Вы получили zipStream. Это должно работать, когда Вы получаете его как это:

  zipStream = zipFile.getInputStream(zipEntry)

при получении ZipInputStream из ZipFile можно получить один поток для 3-й партийной библиотеки, позволить ему использовать его, и Вы получаете другой входной поток с помощью кода прежде.

Помнят, inputstream является курсором. Если у Вас есть все данные (как ZipFile), можно попросить курсоры N по ним.

А различный случай - то, если у Вас только есть "GZip" inputstream, только заархивированный поток байтов. В этом случае Вы буфер ByteArrayOutputStream имеете весь смысл.

0
ответ дан 30 November 2019 в 08:33
поделиться

Проверьте, расположен ли входной поток в просьбу.

Иначе, как реализация: Я не думаю, что необходимо записать в поток результата, в то время как Вы читаете, если Вы не обрабатываете этот точный поток в другом потоке.

Просто создают массив байтов, читают входной поток, затем создают поток вывода.

-1
ответ дан 30 November 2019 в 08:33
поделиться

Пожалуйста, попробуйте код ниже

private static byte[] getZipArchiveContent(File zipName) throws WorkflowServiceBusinessException {

  BufferedInputStream buffer = null;
  FileInputStream fileStream = null;
  ByteArrayOutputStream byteOut = null;
  byte data[] = new byte[BUFFER];

  try {
   try {
    fileStream = new FileInputStream(zipName);
    buffer = new BufferedInputStream(fileStream);
    byteOut = new ByteArrayOutputStream();

    int count;
    while((count = buffer.read(data, 0, BUFFER)) != -1) {
     byteOut.write(data, 0, count);
    }
   } catch(Exception e) {
    throw new WorkflowServiceBusinessException(e.getMessage(), e);
   } finally {
    if(null != fileStream) {
     fileStream.close();
    }
    if(null != buffer) {
     buffer.close();
    }
    if(null != byteOut) {
     byteOut.close();
    }
   }
  } catch(Exception e) {
   throw new WorkflowServiceBusinessException(e.getMessage(), e);
  }
  return byteOut.toByteArray();

 }
0
ответ дан 30 November 2019 в 08:33
поделиться
Другие вопросы по тегам:

Похожие вопросы: