如何从嵌套存档中读取 ZipEntry CRC(zip in zip)

Posted

技术标签:

【中文标题】如何从嵌套存档中读取 ZipEntry CRC(zip in zip)【英文标题】:How to read the ZipEntry CRC from a nested archive (zip in zip) 【发布时间】:2013-10-15 23:35:38 【问题描述】:

查看所选答案的 cmets,问题出在我的测试数据上,而不是代码上。

我正在尝试使用 ZipEntry 对象读取 Zip 存档的 CRC。这适用于直接在文件系统上的 zip。

zStream = new ZipInputStream(new FileInputStream(zipPath))
zEntry = zStream.getNextEntry()
zEntry.getCrc()

我想从嵌套的 zipEntry 中获取 CRC,但我总是返回 -1

zStream = new ZipInputStream(new ZipFile(zipPath).getInputStream(zEntry))
zStream.getNextEntry().getCrc()
// always equal -1

有没有办法在不将嵌套 zip 提取到 FS 的情况下读取 CRC?为什么它不能按原样工作?

【问题讨论】:

您在第二个示例中使用的是哪个 zEntry @SotiriosDelimanolis 嵌套 zip 的 zEntry 也许我今天很慢,但我想看看您尝试从中提取的 zip 结构以及您尝试读取的 CRC。 【参考方案1】:

zStream = new ZipInputStream(new ZipFile(zipPath).getInputStream(zEntry))

那行不通。试试这个:

ZipInputStream innerZip = new ZipInputStream(zStream);

在你找到相关的(外部)ZEntry 之后,迭代innerZip 自己的 ZEntries 并获取他们的 CRC 等,无论你想要什么。

【讨论】:

嵌套的 CRC 仍然返回 -1,而且关闭内部流也会影响外部流。 所以不要关闭它。也许嵌套条目上没有 CRC? 我得出了同样的结论。我查看了嵌套条目(一个签名的 jar),似乎 jarsigner 正在从存档中删除 CRC。【参考方案2】:

如果一个接一个地读取条目,java.util.zip.ZipInputStream 的实现不会传递当前条目的CRC。仅在再次调用 getNextEntry() 后才可用(对于上一个条目)!

AFAIK 这没有记录,但迫切需要。

【讨论】:

【参考方案3】:

这看起来确实是 ZipEntry 界面的错误/限制。应该有一个 API 来计算 CRC。

这里有一些 Groovy 代码来生成缺失的 CRC:

long calculateCRC( zStream) 
    def crc32 = new CRC32()
    crc32.update( IOUtils.toByteArray(zStream))
    return crc32.value

【讨论】:

为什么?除非 zip 文件中有 CRC 可以与之比较,否则这是没有意义的。不是错误。不是限制。 因此您同意 ZipEntry CRC 没有用,除非您手动生成 CRC。我仍然认为 Java Zip API 应该提供这个功能,而不是强迫每个人都在那里滚动自己的 CRC 检查。

以上是关于如何从嵌套存档中读取 ZipEntry CRC(zip in zip)的主要内容,如果未能解决你的问题,请参考以下文章

从文件模式为读取的文件流创建存档 .zip

如何正确关闭嵌套的 ZipInputStreams?

如何在不使用临时文件的情况下从 Java 中的嵌套 zip 文件中读取数据?

无法读取 ZipFile.getInputStream(ZipEntry) 方法返回的 ZipInputStream

熊猫。如何从 ZIP 存档中读取 Excel 文件

如何从 ZipEntry 创建输入流