在 Java 中解压缩巨大的 gz 文件和性能

Posted

技术标签:

【中文标题】在 Java 中解压缩巨大的 gz 文件和性能【英文标题】:unzip huge gz file in Java and performance 【发布时间】:2011-02-14 10:46:02 【问题描述】:

我正在用java解压一个巨大的gz文件,gz文件大约2 gb,解压后的文件大约6 gb。解压缩过程有时会花费很长时间(数小时),有时会在合理的时间内完成(例如不到 10 分钟或更快)。 我有一个相当强大的盒子(8GB ram,4-cpu),有没有办法改进下面的代码?还是使用完全不同的库? 我还使用 Xms256m 和 Xmx4g 到 vm。

public static File unzipGZ(File file, File outputDir) 
    GZIPInputStream in = null;
    OutputStream out = null;
    File target = null;
    try 
        // Open the compressed file
        in = new GZIPInputStream(new FileInputStream(file));

        // Open the output file
        target = new File(outputDir, FileUtil.stripFileExt(file.getName()));
        out = new FileOutputStream(target);

        // Transfer bytes from the compressed file to the output file
        byte[] buf = new byte[1024];
        int len;
        while ((len = in.read(buf)) > 0) 
            out.write(buf, 0, len);
        

        // Close the file and stream
        in.close();
        out.close();
     catch (IOException e) 
        e.printStackTrace();
     finally 
        if (in != null) 
            try 
                in.close();
             catch (IOException e) 
                // TODO Auto-generated catch block
                e.printStackTrace();
            
        
        if (out != null) 
            try 
                out.close();
             catch (IOException e) 
                // TODO Auto-generated catch block
                e.printStackTrace();
            
        
    
    return target;

【问题讨论】:

@user121196:“十亿”和 Java 不太匹配。如果你已经控制了系统并且它是一个 Un*x 盒子,我会考虑在这里调用一个外部进程。这不是很好,但有一个原因是为什么软件操作非常大的文件或非常大量的文件(如 Git、Mercurial 等)不是用 Java 编写的...... 我最终使用了linux原生进程gunzip,它甚至比IOUtil.moveFile更快 相关问题:How to untar a TAR file using Apache Commons. 【参考方案1】:

我不知道默认情况下应用了多少缓冲(如果有的话) - 但您可能想尝试将输入和输出都包装在 BufferedInputStream / BufferedOutputStream 中。您也可以尝试增加缓冲区大小 - 1K 是一个非常小的缓冲区。尝试不同的尺寸,例如16K、64K 等。当然,这些应该使BufferedInputStream 的使用变得不那么重要了。

另一方面,我怀疑这并不是真正的问题。如果它有时在 10 分钟内完成,有时需要几个小时,这表明正在发生一些非常奇怪的事情。当它需要很长时间时,它真的在进步吗?输出文件的大小是否增加?它是否使用大量 CPU?磁盘是否一直在使用?

附注:当您在 finally 块中关闭 inout 时,您也不需要在 try 块中执行此操作。

【讨论】:

【参考方案2】:

如果您有 8 gigs 的 RAM,并且输入文件在 2 gigs 上,您可以尝试使用内存映射文件。 Here 是一个例子。

【讨论】:

【参考方案3】:

尝试使用 java.nio 中的通道,有一种方法可以将字节从一个传输到其他文件通道。然后,您不必自己复制它们。这可能会非常优化。参见 FileInputStream.getChannel()

【讨论】:

以上是关于在 Java 中解压缩巨大的 gz 文件和性能的主要内容,如果未能解决你的问题,请参考以下文章

如何在水壶中解压缩和导入 .tar.gz 文件?

在Linux中解压缩gz文件

linux中解压缩并安装.tar.gz后缀的文件

如何在一次操作中解压缩和 gzip 提取的文件?

如何在iOS中解压缩异步方式的zip文件?

java 如何用zlib解压缩tar.gz文件