我偶尔会在我的应用程序中收到引发start of central directory not found;
zipfile corrupt.
异常的 .zip 文件。这些 zip 文件在我的 Mac 的 Finder 中打开得很好。
我可以每次从命令行修复这些文件,使用zip -FF bad.zip --out good.zip
任何 Java ZIP 库都可以完成同样的事情吗?
您可能只想让 Java 执行此命令,因为严格来说 zip 更像是一个容器,它可以包含不同的压缩算法。
一般来说,使用程序化方法调查和解决与压缩档案相关的问题可能是一项棘手而漫长的任务。
用你的命令试试这个。
我尝试使用 ZipInputStream 和 ZipOutputStream。但是 ZipInputStream 在执行以下操作时总是会失败:“getNextEntry()”。基本上是“getNextEntry()”中的以下代码行:
...
if ((entry = readLOC()) == null) {
return null;
}
...
一些条目后返回 null ,我无法更进一步。
但最后我可以使用 ZipFile 和 ZipOutputStream 解决这个问题,因为 ZipFile 可以毫无问题地读取所有 zip 条目,并且解决方案如下所示:
protected void repairZipFile(String file) throws IOException {
File repairZipFile = new File(file+".repair");
ZipFile zipFile = new ZipFile(file);
Enumeration<? extends ZipEntry> zipFileEntries = zipFile.entries();
InputStream zis;
ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(repairZipFile));
byte[] b = new byte[1024];
while(zipFileEntries.hasMoreElements()){
ZipEntry zipEntry = zipFileEntries.nextElement();
zos.putNextEntry(zipEntry);
zis = zipFile.getInputStream(zipEntry);
int n = zis.read(b);
while(n>=0) {
zos.write(b, 0, n);
n = zis.read(b);
}
zis.close();
zos.closeEntry();
}
zipFile.close();
zos.flush();
zos.close();
Files.move(repairZipFile.toPath(), (new File(file)).toPath(), StandardCopyOption.REPLACE_EXISTING);
}
在 Java 中打开 ZIP 文件有两种方法,使用ZipFile类或使用ZipInputStream。
据我记得,ZipFile
首先读取 zip 文件的中心目录 - 它可以这样做,因为它使用了一个RandomAccessFile
底层。但是,ZipInputStream
使用内联条目信息,如果我认为存在于文件末尾的中央目录丢失或损坏,这可能会更好。
因此,可以通过使用 ZipInputStream 读取 ZIP 文件并使用 ZipOutputStream 将其写回另一个文件,在它们之间复制条目信息来“修复”Java 中的 ZIP 文件。如果 ZipInputStream 被截断,您最终可能会从 ZipInputStream 的最后一个条目中读取 IO 异常,但它可能仍会保存文件中的其他先前条目。