2011-01-11 42 views
5

我有一些关于java.util.zip库的一般问题。 我们基本上做的是导入和导出许多小组件。以前这些成分是进口和使用单个大文件,例如:java.util.zip - ZipInputStream v.s. ZipFile

<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文件。我们不想在我们的系统中爆炸拉链。我们不希望为每个小文件打开单独的流。我目前的问题:

Q1。可能ZipInputStream保证压缩条目(小文件)的读取顺序与我们使用ZipOutputStream的导出时插入的顺序相同?我认为阅读是一样的东西:


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

我知道,中央拉链目录将被置于在zip文件的末尾但尽管如此里面的文件条目具有顺序。我也知道依靠这个命令是一个丑陋的想法,但我只想记住所有的事实。 Q2302。如果我使用ZipFile(我更喜欢),那么调用getInputStream()几百次会带来怎样的性能影响?它会比ZipInputStream解决方案慢吗?该邮编只打开一次,ZipFile支持RandomAccessFile - 这是正确的吗? 我假设读数是这样的:


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线程安全地检索输入流(例如,我可以同时在不同线程中读取不同的条目)?任何表现处罚?

感谢您的回答!

回答

3

问题1:是的,订单将与添加条目相同。 Q2:请注意,由于zip档案文件的结构和压缩,没有任何解决方案是完全流式传输的;他们都做了一定程度的缓冲。如果您签出JDK源代码,实现将共享大部分代码。尽管索引允许查找与条目相对应的块,但内容中没有真正的随机访问。所以我认为不应该有意义的性能差异;特别是操作系统无论如何都会缓存磁盘块。您可能只想测试性能以通过简单的测试用例来验证。

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

+0

嗨StaxMan!我只是在JDK6中检查ZipFile $ ZipFileInputStream的实现。这是由ZipFile.getInputStream返回它有同步,但我真的不知道这是多么可靠。 – 2011-01-11 18:05:14

+0

是的,我不能肯定地说它是非线程安全的。另一个更危险的部分是底层本地zlib库,我怀疑它不是线程安全的。 – StaxMan 2011-01-11 18:07:35

0

关于Q3,在JENKINS-14362经验表明,zlib的是不是线程安全甚至无关的流,即操作时,它有一些不正确的共享静止状态。没有证明,只是一个警告。

1

我测量到,只列出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); 

(不要在同一类运行它们。让两个不同的类,并分别运行它们)