编辑:另一个建议...
从Apache Commons实现中查看ZipFile
,看起来很容易为您的项目有效地分叉。创建一个包装器,包装您的字节数组,其中有所有所需的RandomAccessFile
API的部件(我认为没有很多)。您已经表明您更喜欢ZipFile
的接口,那就选择它吧。
我们不了解您的项目是否会引起任何法律问题,即使您提供了详细信息,我也怀疑这里没有人能够给出好的法律建议,但我认为只需要一两个小时就可以使这个解决方案运作起来,并且我相信您会对此有合理的信心。
编辑:这可能是一个稍微更有成效的答案...
如果您担心条目不连续,但又不想自己处理所有压缩方面的问题,您可以考虑一种选项,其中您有效地重写数据。创建一个新的ByteArrayOutputStream
,并在结尾处读取中央目录。对于中央目录中的每个条目,在输出流中以您认为ZipInputStream
将满意的格式写出一个条目(标头+数据)。然后编写一个新的中央目录 - 如果您希望替换有效,则可能需要从头开始进行此操作,但如果您使用的是您知道实际上不会读取中央目录的代码,则可以提供原始代码。只要它以正确的签名开头,那就足够好了:)
完成后,将ByteArrayOutputStream
转换为新的byte[]
,将其包装在ByteArrayInputStream
中,然后将其传递给ZipInputStream
或ZipArchiveInputStream
。
根据您的目的,您可能甚至不需要做那么多工作 - 您可以通过创建一个“迷你”zip文件,每次从目录中读取一个条目来提取每个文件。
这确实涉及了解zip文件格式,但并不完全需要 - 只需了解其框架即可。这不是像完全使用现有API那样快速简便的修复方法,但也不应该花费太长时间。它不能保证能够读取所有无效文件(怎么可能呢?),但它将保护您免受您特别担心的“条目之间的数据”问题的影响。希望这至少是一个有用的想法...
没有一种方式可以说“这是一个zip文件的字节数组,请使用它”
是有的:
byte[] data = ...;
ByteArrayInputStream byteStream = new ByteArrayInputStream(data);
ZipInputStream zipStream = new ZipInputStream(byteStream);
这就涉及到
ZipInputStream
是否能够处理您提供的所有zip文件的问题,但我不会那么快地放弃它。
当然,还有其他可用的API。例如,您可以查看
Apache Commons Compress。尽管
ZipFile
需要一个文件,但
ZipArchiveInputStream
不需要 - 所以您可以再次使用
ByteArrayInputStream
。编辑:看起来
ZipArchiveStream
也不从中央目录中读取。我希望它会使用
markSupported
事先进行检查,但似乎并没有...
编辑:在问题的评论中,我问过您在哪里读到zip文件不必包含条目数据。您引用了维基百科:
"正确读取zip档案的工具必须扫描各个字段,即zip中央目录的签名。它们不能扫描条目,因为只有目录指定文件块的起始位置。扫描可能会导致误报,因为该格式不禁止在块之间或包含这些签名的未压缩流中存在其他数据。"
“这并不意味着条目数据是可选的。它是说可能有额外的数据存在于尴尬的地方,而不是条目可能完全不存在。它基本上是说不能假设条目是连续的。我可以很乐意承认ZipInputStream可能没有读取文件末尾处的中央目录,但找到处理不存在条目数据的代码与找到处理中央目录的代码并不相同。”
“你随后写道:我可能进一步补充说,无论zip文件是否有效都不是我的关注点。我的关注点是使用它。”
“...这表明你想要处理无效zip文件的代码。再加上这个:我还没有访问我将要处理的zip文件,所以我不知道是否能通过流处理它们。”
这意味着你需要编写处理zip文件的代码,即使它们以无法预测的方式无效。如果我给你1000个随机字节,根本不是zip文件,你会怎么做呢?
基本上,在能够确定问题更紧密之前,甚至说一个特定的库是否是有效的解决方案都是不可行的。从各个地方收集一组zip文件是合理的,这些文件可能无效,但是这些无效方式是被充分理解的,可以说“我必须能够支持所有这些文件”。后来,如果发现这样做不够好,您可能需要做一些工作。但是,能够支持任何东西,无论多么损坏,都不是一个有效的要求。
ZipInputStream
无法读取的压缩文件。也许这种情况会发生,但我认为这可能是很少见的。我唯一注意到的真正问题是,对单个ZipInputStream
实例的不正确同步访问可能会触发本地代码中的并发异常,进而迅速导致整个JVM崩溃。需要注意的是,Java使用这些相同的类来从JAR文件中加载类,因此在适当使用时,它们应该是相当健壮的。 - aroth