如何检查生成的zip文件是否已损坏?

我们有一段代码在我们的系统上生成一个zip文件。 一切都很好,但有时这个由FilZip或WinZip打开的zip文件被认为已损坏。

所以这是我的问题:如果生成的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 🙁

但主要问题仍然存在: 如何以编程方式validation给定的zip文件是否未损坏?

您可以使用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) { } } } 

我知道它已经发布了一段时间,我已经使用了你们所有人提供的代码并想出了这个。 这对于实际问题非常有用。 检查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; } } } 

我想你会在zip文件生成过程中看到对应的exception堆栈跟踪。 所以,你可能不想增强你的exception处理。

在我的实现中它看起来像那样。 也许它可以帮助你:

 //[...] 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 

也许交换以下两行?

 fis.close(); zos.closeEntry(); 

我可以想象closeEntry()仍然会从流中读取一些数据。

你的代码基本上没问题,试着找出哪个文件负责损坏的zip文件。 检查digitalFile.getFile()是否始终向FileInputStream返回有效且可访问的参数。 只需在代码中添加一点日志记录,就会发现问题所在。

 new ZipFile(file) 

压缩文件,所以重复努力,这不是你想要的。 尽管事实上只检查一个文件和问题压缩n文件。

请看一下: http : //www.kodejava.org/examples/336.html

为您的zip创建校验和:

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

当你完成压缩显示它

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

您必须使用java或其他工具检查zip是否与校验和匹配。

有关更多信息,请参阅https://stackoverflow.com/a/10689488/848072

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();