在不将其写入磁盘的情况下访问Zip文件中的随机数据

7

我有一个1-2GB的zip文件,其中包含500-1000k个条目。我需要在几分之一秒内按名称获取文件,而无需完全解压缩。如果文件存储在硬盘上,这将很好地工作:

public class ZipMapper {
    private HashMap<String,ZipEntry> map;
    private ZipFile zf;

    public ZipMapper(File file) throws IOException {
        map = new HashMap<>();
        zf = new ZipFile(file);

        Enumeration<? extends ZipEntry> en = zf.entries();
        while(en.hasMoreElements()) {
            ZipEntry ze = en.nextElement();
            map.put(ze.getName(), ze);
        }
    }

    public Node getNode(String key) throws IOException {
        return Node.loadFromStream(zf.getInputStream(map.get(key)));
    }
}

如果程序从Amazon S3下载了zip文件并拥有其InputStream(或字节数组),那么我该怎么办?尽管下载1GB只需要约1秒钟,但将其写入硬盘可能需要一些时间,并且处理多个文件略微困难,因为我们没有硬盘垃圾回收器。

ZipInputStream不允许随机访问条目。

创建一个通过字节数组在内存中的虚拟文件会很好,但我找不到方法。


你看过TrueZip库吗?它可以让你像处理普通文件一样处理ZIP条目,如果我没记错的话,还可以通过http(s)访问远程zip文件。 - RudolphEst
5个回答

2

您可以标记文件在退出时删除。

如果您想采用内存方法:请查看新的NIO.2文件API。Oracle为zip / jar提供了一个文件系统提供程序,而AFAIK ShrinkWrap则提供了一种内存文件系统。您可以尝试两者的组合。

我编写了一些实用程序方法,使用NIO.2文件API(该库是开源的)将目录和文件复制到/从Zip文件:

Maven:

<dependency>  
    <groupId>org.softsmithy.lib</groupId>  
    <artifactId>softsmithy-lib-core</artifactId>  
    <version>0.3</version>  
</dependency>  

教程:

http://softsmithy.sourceforge.net/lib/current/docs/tutorial/nio-file/index.html

API: CopyFileVisitor.copy

特别是PathUtils.resolve有助于解决跨文件系统的路径问题。

注:本文为IT技术相关内容,涉及到一些专业术语和知识点,翻译时需要注意保持准确性并尽量使内容通俗易懂。同时保留HTML标签,不做解释。

1
你可以使用SecureBlackbox库,在任何可寻址的流上执行ZIP操作。

我下载了这个库,但是找不到有关java/zip的任何文档或参考资料。 - user1766873
是的。Java文档尚未准备好,但大多数方法与库的.NET版本具有相同的命名,因此您可以在http://eldos.com/documentation/sbb/documentation/ref_cl_zipreader.html上查看文档。 - Nickolay Olshevsky
提取方法只能写入“outputPath”。无法获取字节数组或流。 - user1766873
如果outputPath是空字符串,则提取将在Entry.ExtractionStream中完成或通过OnExtractionStreamNeeded事件处理。 - Nickolay Olshevsky

0


我认为你应该考虑使用操作系统来创建“内存”文件系统(即RAM驱动器)。
此外,看一下文件系统的API。


我认为这是唯一可行的解决方案。最终,我选择写入硬盘驱动器,因为在我的情况下它非常快速。 - user1766873

0
一个完全不同的方法:如果服务器已经在磁盘上拥有文件(并且可能已经缓存在内存中),那么可以直接让它给你这些文件。换句话说,提交需要的文件,然后在服务器上提取和传递这些文件。

0

Blackbox库只有Extract(String name, String outputPath)方法。看起来它确实可以随机访问可寻址的zip流中的任何文件,但它无法将结果写入字节数组或返回流。

我找不到ShrinkWrap的任何文档。我找不到任何适合的FileSystem/FileSystemProvider等实现。

然而,事实证明,我正在运行的Amazon EC2实例(大型)以某种方式在约1秒钟内将1GB文件写入磁盘。所以我只需将文件写入磁盘并使用ZipFile即可。

如果HDD速度较慢,我认为RAM磁盘将是最简单的解决方案。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接