Подтвердить что ты не робот

Предпочтительный способ использования Java ZipOutputStream и BufferedOutputStream

В Java важно ли сначала создать ZipOutputStream, или BufferedOutputStream первый? Пример:

FileOutputStream dest = new FileOutputStream(file);
ZipOutputStream zip = new ZipOutputStream(new BufferedOutputStream(dest));

// use zip output stream to write to

Или:

FileOutputStream dest = new FileOutputStream(file);
BufferedOutputStream out = new BufferedOutputStream(new ZipOutputStream(dest));

// use buffered stream to write to

В моих ненаучных таймингах я, похоже, не очень разбираюсь в различиях. Я не вижу ничего в Java API, который говорит, что один из этих способов является необходимым или предпочтительным. Любой совет? Похоже, что сначала сжимает вывод, а затем буферизирует его для записи, будет более эффективным.

4b9b3361

Ответ 1

Вы всегда должны обернуть BufferedOutputStream с помощью ZipOutputStream, а не наоборот. См. Приведенный ниже код:

FileOutputStream fos = new FileOutputStream("hello-world.zip");
BufferedOutputStream bos = new BufferedOutputStream(fos);
ZipOutputStream zos = new ZipOutputStream(bos);

try {
    for (int i = 0; i < 10; i++) {
        // not available on BufferedOutputStream
        zos.putNextEntry(new ZipEntry("hello-world." + i + ".txt"));
        zos.write("Hello World!".getBytes());
        // not available on BufferedOutputStream
        zos.closeEntry();
    }
}
finally {
    zos.close();
}

Как говорится в комментариях, методы putNextEntry() и closeEntry() недоступны в BufferedOutputStream. Без вызова этих методов ZipOutputStream генерирует исключение java.util.zip.ZipException: no current ZIP entry.

Для полноты, стоит отметить, что предложение finally вызывает только close() на ZipOutputStream. Это связано с тем, что по соглашению все встроенные средства оболочки потока вывода Java распространяют закрытие.

ИЗМЕНИТЬ

Я просто тестировал это наоборот. Оказывается, что обертка ZipOutputStream с BufferedOutputStream, а затем только вызов write() на нем (без создания/закрытия записей) не будет бросать ZipException. Вместо этого полученный ZIP файл будет поврежден, без каких-либо записей внутри него.

Ответ 2

Вы должны:

ZipOutputStream out =  new ZipOutputStream(new BufferedOutputStream(dest));

потому что вы хотите буферизировать запись на диск (потому что это намного эффективнее в больших блоках данных, чем во многих маленьких).


Это

new BufferedOutputStream(new ZipOutputStream(dest));

будет буферизовать перед сжатием zip. Но все это происходит в памяти и не нуждается в буферизации, потому что много небольших обращений к памяти примерно одинаковой скорости, чем несколько больших. В общем объеме памяти необходимое время пропорционально количеству байтов чтения/записи.

Как упоминалось в комментариях:

Методы ZipOutputStream, которые не являются частью BufferedOutputStream, также недоступны. Например. putNextEntry и closeEntry.