随机访问Zip文件而不将其写入磁盘

时间:2013-02-27 13:06:39

标签: java zip

我有一个1-2GB的zip文件,500-1000k条目。我需要在几分之一秒内按名称获取文件,而不需要完全解压缩。如果文件存储在HDD上,这可以正常工作:

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不允许随机访问条目。

通过字节数组在内存中创建虚拟文件会很不错,但我找不到办法。

5 个答案:

答案 0 :(得分:1)

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

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

我已经编写了一些实用程序方法,使用NIO.2文件API(库是开源的)将目录和文件复制到Zip文件/从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有助于解决跨文件系统的路径。

答案 1 :(得分:1)

您可以使用SecureBlackbox库,它允许对任何可搜索流进行ZIP操作。

答案 2 :(得分:0)


我认为您应该考虑使用您的操作系统来创建“内存”文件系统(即RAM驱动器)。
另外,请查看FileSystem API。

答案 3 :(得分:0)

一种完全不同的方法:如果服务器在磁盘上有文件(并且可能已经缓存在RAM中):让它直接为您提供文件。换句话说,提交您需要的文件,然后注意在服务器上提取和提供这些文件。

答案 4 :(得分:0)

Blackbox库只有Extract(String name,String outputPath)方法。似乎它可以随机访问可搜索zip-stream中的任何文件,但它无法将结果写入字节数组或返回流。

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

然而,事实证明我正在运行的Amazon EC2实例(大)以1秒的速度将1gb文件写入磁盘。所以我只是将文件写入磁盘并使用ZipFile。

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