Закрытие ZipOutputStream

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

ZipOutputStream zos = null; 
try
{
    zos = new ZipOutputStream(new FileOutputStream("..."));
    //
    //..
    //
}
finally
{
    zos.close();
}

Если по какой-то причине не было добавлено записей zip (возможно, исключительная ситуация), то при попытке закрыть будет сделано следующее исключение:

Exception in thread "main" java.util.zip.ZipException: ZIP file must have at least one entry
    at java.util.zip.ZipOutputStream.finish(ZipOutputStream.java:304)
    at java.util.zip.DeflaterOutputStream.close(DeflaterOutputStream.java:146)
    at java.util.zip.ZipOutputStream.close(ZipOutputStream.java:321)

В этой ситуации будет самый чистый способ закрыть поток?

Спасибо...

Ответ 1

Вы должны закрыть FileOutputStream, а не ZipOutputStream, потому что первое - это то, что фактически потребляет системные ресурсы.

File zipFile = new File("/tmp/example.zip");
FileOutputStream fos = null;
try
{
   fos = new FileOutputStream(zipFile);
   ZipOutputStream zos = new ZipOutputStream(fos);

   // ...

   zos.close();
}
catch (IOException ex)
{
   // log/report exception, then delete the invalid file
   IOUtils.closeQuietly(fos);
   zipFile.delete();
}
finally
{
   IOUtils.closeQuietly(fos);
}

Класс IOUtils находится в Jakarta Commons IO. Использование этого означает, что вам не нужно иметь дело с возможным, но редко полезным IOException, которое может быть выбрано close().

Ответ 2

Вы должны отслеживать, добавили ли вы материал zip-потока и закрыли его только тогда, когда все было добавлено:

ZipOutputStream zos = null; 
OutputStream file = new FileOutputStream("...")
int itemsAdded=0;
try
{
    zos = new ZipOutputStream(file);
    //
    //..
    // itemsAdded++; 
}
finally
{
    if ( itemsAdded > 0 ) {
         zos.close();
    } else {
         file.close();
    }
}

если вам не нужен счет, используйте флаг boolean.

Ответ 3

Вместо того, чтобы закрывать поток только при добавлении вещей, то, что я сделал, является проверкой состояния, чтобы увидеть, есть ли что-нибудь для zip, перед запуском почтового индекса. Это помогло мне упростить этот процесс, и я думаю, что он может использоваться в целом для обработки проблемы "ZIP файл должен иметь хотя бы одну запись". Правда, что закрытие zos может вызывать другие исключения, но это редко.

Я думаю, что это проблема с Java, которая не обрабатывает случай, когда нет файлов для zip.

то есть:

int itemsToAdd=0;
//....

if ( itemsToAdd > 0 ) {

    ZipOutputStream zos = new ZipOutputStream(file);
    try {
        //add files to zip
    }
    finally {
        zos.close();
    }
}