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

java.util.zip-ZipInputStream v.s.ZipFile,java,thread-safety,io,zip,Java,Thread Safety,Io,Zip,我有一些关于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"/> <compone

我有一些关于
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"/>
我知道中央zip目录放在zip文件的末尾,但是里面的文件条目有顺序。我也知道依赖订单是一个丑陋的想法,但我只想把所有的事实都记在心里

问题2。如果我使用
ZipFile
(我更喜欢),数百次调用
getInputStream()
对性能有什么影响?它会比ZipInputStream解决方案慢很多吗?zip仅打开一次,并且
ZipFile
RandomAccessFile
支持-这是否正确? 我假设阅读是这样的:


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

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));
}
第三季度。从同一
ZipFile
中检索的输入流是否线程安全(例如,我可以同时读取不同线程中的不同条目)?有任何表现处罚吗


谢谢你的回答

Q1:是的,添加条目的顺序相同

问题2:请注意,由于zip存档文件的结构和压缩,没有一种解决方案是完全流式的;它们都有一定程度的缓冲。如果您查看JDK源代码,那么实现会共享大部分代码。虽然索引允许查找与条目对应的块,但并没有真正的随机访问内容。因此,我认为不应该存在有意义的绩效差异;特别是操作系统无论如何都会缓存磁盘块。您可能只想测试性能,用一个简单的测试用例来验证这一点


问题3:我不会指望这一点;很可能他们不是。如果您真的认为并发访问会有帮助(主要是因为解压是CPU限制的,所以可能会有帮助),我会尝试在内存中读取整个文件,通过ByteArrayInputStream公开,并构造多个独立的读卡器。

关于Q3,中的经验表明,即使在不相关的流上操作,zlib也不是线程安全的,也就是说,它有一些不正确的共享静态。未经验证,只是一个警告。

我测量到,仅使用
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);

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

使用ZipFile.getInputStream()比使用新的ZipInputStream()要快得多。你自己试试。

嗨,斯塔克斯曼!我只是在检查JDK6中ZipFile$ZipFileInputStream的实现。这是由ZipFile.getInputStream返回的,它有同步,但我真的不知道它有多可靠。是的,我不能肯定它是非线程安全的。另一个更危险的部分是底层的原生zlib库,我怀疑它不是线程安全的。通过痛苦的经历,我可以证明它不是线程安全的。我的直觉是ZipFile正在读取zip索引,而ZipInputStream正在“循环”整个zip文件,读取一个又一个文件,FWIW。
    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);