Как проверить, поврежден ли сгенерированный zip файл?
у нас есть фрагмент кода, который генерирует 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);
}
Есть ли что-то, что мы делаем здесь неправильно?
EDIT:
На самом деле, код выше абсолютно нормально. Моя проблема заключалась в том, что я перенаправлял поток WRONG для своих пользователей. Итак, вместо открытия zip файла они открывают что-то совершенно другое. Mea culpa: (
НО главный вопрос остается: как программно я могу проверить, не поврежден ли данный zip файл?
Ответы
Ответ 1
Вы можете использовать класс 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) {
}
}
}
Ответ 2
Я знаю, что это было какое-то время, когда это было опубликовано, я использовал код, который вы указали, и придумал это. Это отлично работает для актуального вопроса. Проверка, поврежден ли 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
Я думаю, что при генерации zip файла вы увидите корреспондентскую трассировку стека исключений. Таким образом, вы, вероятно, не улучшите обработку исключений.
Ответ 4
в моей реализации это выглядит так. возможно, это поможет вам:
//[...]
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
Ответ 5
Возможно, замените следующие две строки:
fis.close();
zos.closeEntry();
Я могу представить, что closeEntry() все равно будет считывать некоторые данные из потока.
Ответ 6
Ваш код в основном в порядке, попробуйте выяснить, какой файл отвечает за поврежденный zip файл. Проверьте, действительно ли функция digitalFile.getFile() возвращает действительный и доступный аргумент в FileInputStream. Просто добавьте бит в свой код, и вы узнаете, что не так.
Ответ 7
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 или других инструментов, проверяющих соответствие контрольных сумм.
см. fooobar.com/questions/242582/... для получения дополнительной информации
Ответ 8
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();