用Java解压巨大的gz文件并提高性能

用Java解压巨大的gz文件并提高性能,java,compression,gzip,Java,Compression,Gzip,我正在用java解压一个巨大的gz文件,gz文件大约为2GB,解压后的文件大约为6GB。解压过程有时会花费很长时间(数小时),有时会在合理的时间内完成(比如10分钟以下或更快)我有一个功能相当强大的机箱(8GB ram,4-cpu),有没有办法改进下面的代码?或者使用一个完全不同的库?我也使用Xms256m和Xmx4g来支持虚拟机 public static File unzipGZ(File file, File outputDir) { GZIPInputStream in = nu

我正在用java解压一个巨大的gz文件,gz文件大约为2GB,解压后的文件大约为6GB。解压过程有时会花费很长时间(数小时),有时会在合理的时间内完成(比如10分钟以下或更快)
我有一个功能相当强大的机箱(8GB ram,4-cpu),有没有办法改进下面的代码?或者使用一个完全不同的库?
我也使用Xms256m和Xmx4g来支持虚拟机

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;
}

如果您有8 Gig的RAM,并且输入文件为2 Gig,则可以尝试使用内存映射文件。是一个如何实现的示例。

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

另一方面,我怀疑这不是真正的问题。如果它有时在10分钟内完成,有时需要几个小时,那就意味着发生了一些非常奇怪的事情。当这需要很长时间时,它是否真的取得了进展?输出文件的大小是否在增加?它是否使用重要的CPU?磁盘是否一直在使用


一方面注意:当您在finally块中关闭
in
out
时,您不需要在
try
块中也这样做。

尝试使用java.nio中的通道,使用一种方法将字节从一个文件通道传输到其他文件通道。那你就不必自己复制了。这可能会非常优化。请参阅FileInputStream.getChannel()

@user121196:“数十亿”和Java并不匹配。如果你对系统有控制权,如果它是UNX框,我会考虑在这里调用外部进程。这不太好,但有一个原因,就是操纵非常大的文件或非常大数量的文件(如Git、Mercurial等)的软件不是用Java编写的……我最终使用了linux本机进程gunzip,它甚至比IOUtil.moveFileRelated更快。