java.util.zip - ZipInputStream v.s. ZipFile的

问题描述 投票:7回答:3

我对java.util.zip库有一些一般性的问题。我们基本上做的是导入和导出许多小组件。以前这些组件是使用单个大文件导入和导出的,例如:

<component-type-a id="1"/>
<component-type-a id="2"/>
<component-type-a id="N"/>

<component-type-b id="1"/>
<component-type-b id="2"/>
<component-type-b id="N"/>

请注意,导入期间组件的顺序是相关的。

现在每个组件都应该占用自己的文件,该文件应该是外部版本的,QA-ed,bla,bla。我们决定导出的输出应该是一个zip文件(包含所有这些文件),我们导入的输入应该是一个类似的zip文件。我们不想在我们的系统中爆炸zip。我们不希望为每个小文件打开单独的流。我目前的问题:

Q1。可能ZipInputStream保证zip条目(小文件)将按照我们使用ZipOutputStream的导出插入的顺序读取吗?我认为阅读是这样的:


ZipInputStream zis = new ZipInputStream(new BufferedInputStream(fis));
ZipEntry entry;
while((entry = zis.getNextEntry()) != null) 
{
       //read from zis until available
}

我知道中央zip目录放在zip文件的末尾但是内部的文件条目有顺序。我也知道依靠订单是一个丑陋的想法,但我只想记住所有的事实。

Q2。如果我使用ZipFile(我更喜欢)调用getInputStream()数百次的性能影响是什么?它会比ZipInputStream解决方案慢得多吗?拉链仅打开一次,ZipFileRandomAccessFile支持 - 这是正确的吗?我认为阅读是这样的:


ZipFile zipfile = new ZipFile(argv[0]);
Enumeration e = zipfile.entries();//TODO: assure the order of the entries
while(e.hasMoreElements()) {
        entry = (ZipEntry) e.nextElement();
        is = zipfile.getInputStream(entry));
}

Q3。从相同的ZipFile线程检索的输入流是否安全(例如,我可以同时读取不同线程中的不同条目)吗?任何表现处罚?

谢谢你的回答!

java thread-safety io zip
3个回答
4
投票

Q1:是的,订单与添加条目的顺序相同。

Q2:请注意,由于zip存档文件的结构和压缩,没有一个解决方案正是流媒体;他们都做了一定程度的缓冲。如果您查看JDK源代码,实现将共享大多数代码。内容中没有真正的随机访问,尽管索引确实允许查找与条目对应的块。所以我认为应该没有有意义的性能差异;特别是因为OS无论如何都会对磁盘块进行缓存。您可能只想测试性能以通过简单的测试用例来验证这一点。

Q3:我不指望这个;而且很可能他们不是。如果你真的认为并发访问会有所帮助(主要是因为解压缩是CPU绑定的,所以它可能有帮助),我会尝试在内存中读取整个文件,通过ByteArrayInputStream公开,并构建多个独立的读者。


2
投票

我测量只用ZipInputStream列出文件比用ZipFile慢8倍。

    long t = System.nanoTime();
    ZipFile zip = new ZipFile(jarFile);
    Enumeration<? extends ZipEntry> entries = zip.entries();
    while (entries.hasMoreElements())
    {
        ZipEntry entry = entries.nextElement();

        String filename = entry.getName();
        if (!filename.startsWith(JAR_TEXTURE_PATH))
            continue;

        textureFiles.add(filename);
    }
    zip.close();
    System.out.println((System.nanoTime() - t) / 1e9);

    long t = System.nanoTime();
    ZipInputStream zip = new ZipInputStream(new FileInputStream(jarFile));
    ZipEntry entry;
    while ((entry = zip.getNextEntry()) != null)
    {
        String filename = entry.getName();
        if (!filename.startsWith(JAR_TEXTURE_PATH))
            continue;

        textureFiles.add(filename);
    }
    zip.close();
    System.out.println((System.nanoTime() - t) / 1e9);

(不要在同一个类中运行它们。创建两个不同的类并分别运行它们)


0
投票

关于Q3,JENKINS-14362的经验表明,即使在不相关的流上运行,zlib也不是线程安全的,即它有一些不正确的共享静态。没有证明,只是一个警告。

© www.soinside.com 2019 - 2024. All rights reserved.