Как проверить, не поврежден ли сгенерированный zip-файл? - PullRequest
24 голосов
/ 18 января 2010

у нас есть фрагмент кода, который генерирует zip-файл в нашей системе.Все в порядке, но иногда этот zip-файл при открытии FilZip или WinZip считается поврежденным.

Итак, вот мой вопрос: как мы можем программно проверить, не поврежден ли сгенерированный zip-файл?

Вот код, который мы используем для создания наших zip-файлов:

try {
    ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(tmpFile));
    byte[] buffer = new byte[16384];
    int contador = -1;
    for (DigitalFile digitalFile : document.getDigitalFiles().getContent()) {
       ZipEntry entry = new ZipEntry(digitalFile.getName());
       FileInputStream fis = new FileInputStream(digitalFile.getFile());
       try {
          zos.putNextEntry(entry);
          while ((counter = fis.read(buffer)) != -1) {
             zos.write(buffer, 0, counter);
          }
          fis.close();
          zos.closeEntry();
       } catch (IOException ex) {
          throw new OurException("It was not possible to read this file " + arquivo.getId());
       }
    }
    try {
      zos.close();
    } catch (IOException ex) {
      throw new OurException("We couldn't close this stream", ex);
    }

Есть ли что-то, что мы здесь делаем неправильно?

РЕДАКТИРОВАТЬ: На самом деле, приведенный выше код абсолютно нормально.Моя проблема заключалась в том, что я перенаправлял НЕПРАВИЛЬНЫЙ поток для своих пользователей.Таким образом, вместо открытия zip-файла они открывают что-то совершенно другое.Mea culpa: (

НО остается главный вопрос: как программно я могу проверить, не поврежден ли данный zip-файл?

Ответы [ 8 ]

28 голосов
/ 18 января 2010

Вы можете использовать класс ZipFile для проверки вашего файла:

 static boolean isValid(final File file) {
    ZipFile zipfile = null;
    try {
        zipfile = new ZipFile(file);
        return true;
    } catch (IOException e) {
        return false;
    } finally {
        try {
            if (zipfile != null) {
                zipfile.close();
                zipfile = null;
            }
        } catch (IOException e) {
        }
    }
}
9 голосов
/ 21 июня 2013

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

private boolean isValid(File file) {
    ZipFile zipfile = null;
    ZipInputStream zis = null;
    try {
        zipfile = new ZipFile(file);
        zis = new ZipInputStream(new FileInputStream(file));
        ZipEntry ze = zis.getNextEntry();
        if(ze == null) {
            return false;
        }
        while(ze != null) {
            // if it throws an exception fetching any of the following then we know the file is corrupted.
            zipfile.getInputStream(ze);
            ze.getCrc();
            ze.getCompressedSize();
            ze.getName();
            ze = zis.getNextEntry();
        } 
        return true;
    } catch (ZipException e) {
        return false;
    } catch (IOException e) {
        return false;
    } finally {
        try {
            if (zipfile != null) {
                zipfile.close();
                zipfile = null;
            }
        } catch (IOException e) {
            return false;
        } try {
            if (zis != null) {
                zis.close();
                zis = null;
            }
        } catch (IOException e) {
            return false;
        }

    }
}
3 голосов
/ 18 января 2010

Я думаю, вы увидите соответствующую трассировку стека исключений во время генерации zip-файла. Таким образом, вы, вероятно, не хотите улучшать обработку исключений.

2 голосов
/ 20 января 2011

в моей реализации это выглядит так. может быть, это поможет вам:

//[...]

try {
    FileInputStream fis = new FileInputStream(file);
    BufferedInputStream bis = new BufferedInputStream(fis);

    zos.putNextEntry(new ZipEntry(file.getName()));

    try {
        final byte[] buf = new byte[BUFFER_SIZE];
        while (true) {
            final int len = bis.read(buf);
            if (len == -1) {
                break;
            }
            zos.write(buf, 0, len);
        }
        zos.flush();
        zos.closeEntry();
    } finally {
        try {
            bis.close();
        } catch (IOException e) {
            LOG.debug("Buffered Stream closing failed");
        } finally {
            fis.close();
        }
    }
} catch (IOException e) {
    throw new Exception(e);
}

//[...]
zos.close
1 голос
/ 27 сентября 2012
new ZipFile(file) 

снова сожмите файл, так что дублируйте усилия, и это не то, что вы ищете. Несмотря на то, что проверяют только один файл и вопрос сжимает n-файлы.

Взгляните на это: http://www.kodejava.org/examples/336.html

Создайте контрольную сумму для вашего почтового индекса:

CheckedOutputStream checksum = new CheckedOutputStream(fos, new CRC32());
ZipOutputStream zos = new ZipOutputStream(new BufferedOutputStream(checksum));
...

А когда закончишь сжатие покажи

System.out.println("Checksum   : " + checksum.getChecksum().getValue());

Вы должны сделать то же самое, читая zip с помощью Java или других инструментов, проверяя, совпадают ли контрольные суммы.

см. https://stackoverflow.com/a/10689488/848072 для получения дополнительной информации

1 голос
/ 18 января 2010

Ваш код в основном в порядке, попробуйте выяснить, какой файл отвечает за поврежденный почтовый файл.Проверьте, всегда ли digitalFile.getFile () возвращает действительный и доступный аргумент для FileInputStream.Просто добавьте немного регистрации в ваш код, и вы поймете, что не так.

1 голос
/ 18 января 2010

Возможно, поменять местами две следующие строки?

0 голосов
/ 18 января 2010

ZipOutputStream не закрывает базовый поток.

Что вам нужно сделать:

FileOutputStream fos = new FileOutputStream(...);
ZipOutputStream zos = new ZipOutputStream(fos);

Затем в вашем закрывающем блоке:

zos.close();
fos.flush(); // Can't remember whether this is necessary off the top of my head!
fos.close();
...