代码之家  ›  专栏  ›  技术社区  ›  Tim

在java中,有没有更快的方法将字节数组写入文件?

  •  -1
  • Tim  · 技术社区  · 3 月前

    我有一个java应用程序,需要能够向Amazon S3存储区域上传和下载大文件。

    我对上传大文件的速度感到惊喜。真的只是几秒钟的问题。

    我也对它下载这些文件并转换为字节数组的速度感到非常满意。

    不过,将字节数组读取到实际文件中太慢了。

    对于如何让最后一部分更快地进行,有什么建议吗?

    这是我的代码,非常感谢。

            // Get the response - this is actually quite fast
            ResponseInputStream<GetObjectResponse> getResponse = s3Client.getObject(request);
            byte[] responseBytes = getResponse.readAllBytes();
    
            // Download to a file - this is extremely slow
            File outputFile = new File(downloadPath);
    
            try (FileOutputStream fileOutputStream = new FileOutputStream(outputFile)) {               
                for (int ii=0; ii<responseBytes.length; ii++) {
                    fileOutputStream.write(responseBytes, ii, 1);
                }
            }
    
    2 回复  |  直到 3 月前
        1
  •  2
  •   Thomas    3 月前

    逐字节写入文件将导致每个字节的系统调用开销。

    幸运的是,有一个超载 write 这需要整个 byte[] 并用更少的系统调用将其写出来:

            try (FileOutputStream fileOutputStream = new FileOutputStream(outputFile)) {               
                fileOutputStream.write(responseBytes);
            }
    
        2
  •  0
  •   Emad Kerhily    3 月前

    在当前代码中,您正在使用循环写入文件:

    for (int ii=0; ii<responseBytes.length; ii++) {
        fileOutputStream.write(responseBytes, ii, 1);
    }
    

    这将一次向文件输出流写入一个字节。由于方法调用和可能的磁盘I/O操作,每次调用fileOutputStream.write()都会产生开销。您可以在一次调用中写入整个字节数组,而不是一次写入一个字节:

    // Write the entire byte array at once - much faster
    try (FileOutputStream fileOutputStream = new FileOutputStream(outputFile){
        fileOutputStream.write(responseBytes);
    }
    

    但是,为了获得更好的性能,请将FileOutputStream包装在BufferedOutputStream中,如下所示:

    import java.io.BufferedOutputStream;
    
    // ...
    
    try (BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(new FileOutputStream(outputFile))) {
        bufferedOutputStream.write(responseBytes);
    }
    

    最后,我认为你必须超越这一点,尽量不要将整个文件读入内存,这可能会导致高内存消耗。您可以直接将对象流式传输到文件中,而无需将其加载到内存中。。