java - Java 的解压缩实用程序性能不佳

标签 java unzip

我注意到与使用 WinZip 等 native 工具相比,Java 中的解压缩工具非常慢。

有没有更高效的 Java 第三方库? 首选开源。

编辑

这是使用 Java 内置解决方案与 7zip 的速度比较。 我在我的原始解决方案中添加了缓冲输入/输出流(感谢 Jim,这确实产生了很大的不同)。

Zip 文件大小:800K Java 解决方案:2.7 秒 7Zip 解决方案:204 毫秒

下面是使用内置Java解压修改后的代码:

/** Unpacks the give zip file using the built in Java facilities for unzip. */
@SuppressWarnings("unchecked")
public final static void unpack(File zipFile, File rootDir) throws IOException
{
  ZipFile zip = new ZipFile(zipFile);
  Enumeration<ZipEntry> entries = (Enumeration<ZipEntry>) zip.entries();
  while(entries.hasMoreElements()) {
    ZipEntry entry = entries.nextElement();
    java.io.File f = new java.io.File(rootDir, entry.getName());
    if (entry.isDirectory()) { // if its a directory, create it
      continue;
    }

    if (!f.exists()) {
      f.getParentFile().mkdirs();
      f.createNewFile();
    }

    BufferedInputStream bis = new BufferedInputStream(zip.getInputStream(entry)); // get the input stream
    BufferedOutputStream bos = new BufferedOutputStream(new java.io.FileOutputStream(f));
    while (bis.available() > 0) {  // write contents of 'is' to 'fos'
      bos.write(bis.read());
    }
    bos.close();
    bis.close();
  }
}

最佳答案

问题不在于解压缩,而是将解压缩数据写回磁盘的低效方式。我的基准测试表明使用

    InputStream is = zip.getInputStream(entry); // get the input stream
    OutputStream os = new java.io.FileOutputStream(f);
    byte[] buf = new byte[4096];
    int r;
    while ((r = is.read(buf)) != -1) {
      os.write(buf, 0, r);
    }
    os.close();
    is.close();

而是将方法的执行时间减少了 5 倍(对于 6 MB 的 zip 文件,从 5 秒减少到 1 秒)。

可能的罪魁祸首是您对 bis.available() 的使用。除了不正确(available 返回字节数,直到对 read 的调用阻塞,直到流结束),这绕过了 BufferedInputStream 提供的缓冲,需要对复制到输出文件中的每个字节进行 native 系统调用。

请注意,如果您像我上面那样使用批量读取和写入方法,则不需要包装在 BufferedStream 中,并且关闭资源的代码不是异常安全的(如果读取或写入因任何原因失败,都不是 isos 都不会被关闭)。最后,如果类路径中有 IOUtils,我建议使用经过良好测试的 IOUtils.copy而不是自己滚动。

关于java - Java 的解压缩实用程序性能不佳,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3321842/

相关文章:

c++ - 将所有文件从 ZIP 存档移动到另一个

ruby - 如何使用 Rubyzip 库覆盖现有文件

ios - 如何在swift中解压ftp下载的数据

java - 在java中解压带有子文件夹的存档吗?

java - 测试文件是否存在

c# - 如何在 C# 中解压 .bz2 文件?

java - maven-compiler-plugin 3.0 不编译 maven 下的资源文件夹

java - 如何在 Julia 中使用并行性来加速组合检查?

java - 创建一个泛型类,其类型参数仅限于某个父类(super class)

java - 前 1000 个质数之和