Многие объяснения уже присутствуют, чтобы объяснить, как это происходит и как это исправить, но вы также должны следовать рекомендациям, чтобы избежать NullPointerException
вообще.
См. также: A хороший список лучших практик
Я бы добавил, очень важно, хорошо использовать модификатор final
. Использование "окончательной" модификатор, когда это применимо в Java
Сводка:
final
для обеспечения хорошей инициализации. @NotNull
и @Nullable
if("knownObject".equals(unknownObject)
valueOf()
поверх toString (). StringUtils
StringUtils.isEmpty(null)
. Ваш цикл выглядит допустимым - что следующее кодирует (только на своем собственном) возврат?
zipStream.read(tempBuffer)
, если это возвращается-1, тогда zipStream закрывается, прежде чем Вы получите его, и все ставки выключены. Пора использовать Ваш отладчик и удостовериться, что передается Вам, на самом деле допустимо.
при вызове getNextEntry () он возвращает значение и является данными в значимой записи (т.е. getCompressedSize () возвращают допустимое значение)? ЕСЛИ Вы просто читаете zip-файл, который не имеет считанных вперед записей zip встроенными, то ZipInputStream не собирается работать на Вас.
Некоторые полезные лакомые кусочки о формате Zip:
Каждый файл, встроенный в zip-файл, имеет заголовок. Этот заголовок может содержать полезную информацию (такую как сжатая длина потока, это смещается в файле, CRC) - или это может содержать некоторые волшебные значения, которые в основном говорят, что 'Информация не находится в потоковом заголовке, необходимо проверить заключительную часть сообщения Zip'.
Каждый zip-файл тогда имеет таблицу, которая присоединяется до конца файла, который содержит все записи zip, наряду с реальными данными. Таблица в конце обязательна, и значения в нем должны быть корректными. Напротив, значения, встроенные в поток, не должны быть обеспечены.
при использовании ZipFile он читает таблицу в конце zip. Если Вы используете ZipInputStream, я подозреваю, что getNextEntry () пытается использовать записи, встроенные в поток. Если те значения не определяются, то ZipInputStream понятия не имеет, какой длины поток мог бы быть. Расширять алгоритм сам завершающийся (Вы на самом деле не должны знать несжатую длину потока вывода, чтобы полностью восстановить вывод), но возможно, что версия Java этого читателя не обрабатывает эту ситуацию очень хорошо.
я скажу, что довольно необычно иметь сервлет, возвращая ZipInputStream (намного более распространено получить inflatorInputStream, если Вы собираетесь быть получением сжатое содержание.
Вы, вероятно, пытались читать из 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);
}
}
Я использовал бы IOUtils от свободного городского населения io проект.
IOUtils.copy(zipStream, byteArrayOutputStream);
Вы могли реализовать свою собственную обертку вокруг 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();
}
}
Я назвал бы getNextEntry () на ZipInputStream, пока это не при записи, которую Вы хотите (используйте ZipEntry.getName () и т.д.). Вызов getNextEntry () усовершенствует "курсор" к началу записи, которую это возвращает. Затем используйте ZipEntry.getSize () для определения, сколько байтов необходимо считать использование zipInputStream.read ().
Неясно, как Вы получили zipStream. Это должно работать, когда Вы получаете его как это:
zipStream = zipFile.getInputStream(zipEntry)
t неясен, как Вы получили zipStream. Это должно работать, когда Вы получаете его как это:
zipStream = zipFile.getInputStream(zipEntry)
при получении ZipInputStream из ZipFile можно получить один поток для 3-й партийной библиотеки, позволить ему использовать его, и Вы получаете другой входной поток с помощью кода прежде.
Помнят, inputstream является курсором. Если у Вас есть все данные (как ZipFile), можно попросить курсоры N по ним.
А различный случай - то, если у Вас только есть "GZip" inputstream, только заархивированный поток байтов. В этом случае Вы буфер ByteArrayOutputStream имеете весь смысл.
Проверьте, расположен ли входной поток в просьбу.
Иначе, как реализация: Я не думаю, что необходимо записать в поток результата, в то время как Вы читаете, если Вы не обрабатываете этот точный поток в другом потоке.
Просто создают массив байтов, читают входной поток, затем создают поток вывода.
Пожалуйста, попробуйте код ниже
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();
}