用Java解压缩内存中的ZIP文件

Dan*_*ral 28 java zip

我正在下载包含XML的压缩文件,我想避免在操作它们之前将zip文件写入磁盘,因为延迟要求.但是,java.util.zip对我来说还不够.没有办法说"这是一个zip文件的字节数组,使用它"而不将其转换为流,并且ZipInputStream不可靠,因为它会扫描条目标题(请参阅下面的编辑,了解为什么不可靠).

我还没有访问我将要处理的zip文件,所以我不知道我是否能够通过它来处理它们ZipInputStream,我需要找到一个适用于任何有效ZIP文件的解决方案,作为一旦我投入生产失败的惩罚将会很高.

假设ZipInputStream不起作用,在没有条目头的情况下,我该怎么做才能解决这个问题?我正在使用维基百科的定义,其中包括如何正确解压缩zip文件(下面引用)作为标准.

编辑

Apache Commons Zip库对使用Stream(他们的解决方案和Java)的一些问题进行了很好的描述.我将进一步补充,从维基百科和个人经验来看,条目标题上的大小和crc字段可能无法填充(我在这些字段中的文件为-1).感谢centic提供此链接.

另外,让我引用维基百科的主题:

正确读取zip存档的工具必须扫描各个字段的签名,即zip中心目录.它们不能扫描条目,因为只有目录指定文件块的开始位置.扫描可能导致误报,因为格式不禁止其他数据在块之间或包含此类签名的未压缩流之间.

请注意,ZipInputStream扫描条目,而不是中心目录,这是它的问题.

最终编辑

如果有人感兴趣,可以使用此脚本生成无法ZipInputStream从现有ZIP文件中读取的有效ZIP文件.因此,作为对这个封闭问题的最终编辑,我需要一个可以读取文件的库,例如这个脚本生成的文件.

Jon*_*eet 22

编辑:另一个建议......

看着ZipFile从Apache下议院实现,它看起来不会硬有效餐桌,对您的项目.在你的字节数组周围创建一个包装器,RandomAccessFile它包含所需的所有API部分(我认为不是很多).你已经表明你更喜欢这个界面了ZipFile,为什么不这样做呢?

我们对您的项目了解不足以了解这是否会引发任何法律问题 - 即使您提供了详细信息,我怀疑这里的任何人都能提供良好的法律建议 - 但我怀疑它不会超过一两个小时才能得到这个解决方案并且正在工作,我怀疑你对此有合理的信心.


编辑:这可能是一个稍微有效的答案......

如果您担心条目不连续,但又不想自己处理所有压缩方面,您可能会考虑一个有效重写数据的选项.创建一个新的ByteArrayOutputStream,并在最后读取中心目录.对于中央目录中的每个条目,以您认为ZipInputStream满意的格式将输入(标题+数据)写入输出流.然后编写一个新的中央目录 - 如果您希望您的替换有效,您可能需要从头开始执行此操作,但如果您使用的代码您知道实际上不会读取中心目录,那么您可以只提供原始目录,忽略它可能不会有效的事实.只要从正确的签名开始,这可能就足够了:)

完成后,将其ByteArrayOutputStream转换为新的 byte[],将其包装在a中ByteArrayInputStream,然后将其传递给ZipInputStreamZipArchiveInputStream.

根据您的目的,您甚至可能不需要这么做 - 您可以通过创建一个"迷你"zip文件来提取每个文件,其中只包含您从目录中读取的一个条目.

确实涉及了解zip文件格式,但并不完全 - 只是骨架,有效.这不是一个快速简单的解决方案,如完全使用现有的API,但它不应该花长时间.它不能保证它能够读取所有无效文件(它怎么可能?)但它会保护你免受你似乎特别关注的"条目之间的数据"问题.希望它至少是一个有用的想法......


没有办法说"这是一个zip文件的字节数组,使用它"

就在这里:

byte[] data = ...;
ByteArrayInputStream byteStream = new ByteArrayInputStream(data);
ZipInputStream zipStream = new ZipInputStream(byteStream);
Run Code Online (Sandbox Code Playgroud)

这留下了是否ZipInputStream可以处理你将给它的所有zip文件的问题- 但我不会这么快就把它写下来.

当然,还有其他API可用.例如,您可能需要查看Apache Commons Compress.即使ZipFile需要一个文件,ZipArchiveInputStream也不要 - 所以再次,你可以使用ByteArrayInputStream.编辑:看起来好像ZipArchiveStream 也没有从中央目录读取.我希望它会markSupported事先用来检查,但似乎不是......

编辑:在问题的评论中,我问你在哪里读到zip文件不必包含条目数据.你引用维基百科:

"正确读取zip存档的工具必须扫描各个字段的签名,即zip中心目录.它们不能扫描条目,因为只有目录指定文件块的开始位置.扫描可能导致误报,因为格式不存在禁止其他数据在块之间或包含此类签名的未压缩流之间."

这与入门数据是可选的不同.它说在尴尬的地方可能有额外的数据,而不是条目可能完全丢失.它基本上是说不应该假设条目是连续的.我很高兴地承认ZipInputStream可能没有读取文件末尾的中央目录,但找到与此相关的代码与查找不存在的条目数据的代码不同.

然后你写:

我可能会进一步补充说,拉链是否有效不是我的担忧.使用它是.

...这表明你想要处理无效zip文件的代码.结合这个:

我还没有访问我将要处理的zip文件,所以我不知道我是否能够通过流处理它们

这意味着你要求的代码应该处理无法预测的无效zip文件.你能够拒绝它有多么无效?如果我给你1000个随机字节,而根本没有尝试将它们作为一个zip文件,你到底会用它做什么?

基本上,您需要更紧密地解决问题,然后才能确定特定库是否是有效的解决方案.收集来自不同地方的一组zip文件是合理的,这些文件可能以易于理解的方式无效,并说"我必须能够支持所有这些".如果事实证明那还不够好,你可能需要做一些工作.但是,为了能够支持任何事情,无论多么破碎,都不是一个有效的要求.