【问题标题】:Random-access Zip file without writing it to disk随机访问 Zip 文件而不将其写入磁盘
【发布时间】:2013-02-28 06:28:17
【问题描述】:

我有一个 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 秒,但将其写入 HDD 可能需要一些时间,而且处理多个文件稍微困难一些,因为我们没有 HDD 垃圾收集器。

ZipInputStream 不允许随机访问条目。

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

【问题讨论】:

  • 您看过 TrueZip 库吗?它使您可以像普通文件一样访问 ZIP 条目,如果我没记错的话,它还允许通过 http(s) 访问远程 zip 文件。

标签: java zip


【解决方案1】:

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

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

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

马文:

<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 有助于解决跨文件系统的路径。

【讨论】:

    【解决方案2】:

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

    【讨论】:

    • 我下载了库,但在 java/zip 上找不到任何文档或参考。
    • 是的。 Java 文档尚未准备好,但大多数方法与 .NET 版本的库中的命名相同,因此您可以在 eldos.com/documentation/sbb/documentation/ref_cl_zipreader.html 查看文档
    • 提取方法只能写入outputPath。无法获取字节数组或流。
    • 如果 outputPath 为空字符串,则提取到 Entry.ExtractionStream 或通过 OnExtractionStreamNeeded 事件处理。
    【解决方案3】:


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

    【讨论】:

    • 我认为这是唯一可行的解​​决方案。我最终写了硬盘,因为在我的情况下它非常快。
    【解决方案4】:

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

    【讨论】:

      【解决方案5】:

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

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

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

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-10-21
        • 2022-01-18
        • 2013-04-03
        • 2011-05-09
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多