如何提升Java中将字节数组写入本地文件的速度?
如何提升Java中将字节数组写入本地文件的速度?
兄弟,我一眼就瞅出问题的根源了!你现在的代码是逐个字节往文件里写,这种操作简直是在给磁盘IO“添堵”——磁盘最反感这种频繁的小数据写入了,每写一个字节都要触发一次系统调用,开销大到离谱,速度能快才怪呢😅
问题出在哪?
你这段循环代码:
for (int ii=0; ii<responseBytes.length; ii++) { fileOutputStream.write(responseBytes, ii, 1); }
相当于把一个大文件拆成了几十上百万次单字节写入,磁盘的读写都是按“块”来的,这种细碎的操作完全没有利用到磁盘的批量读写能力,速度自然暴跌。
最快的修复方案:一次性写入整个字节数组
直接用FileOutputStream自带的write(byte[])方法,一次性把整个字节数组写入文件,这会让磁盘以最优的方式批量处理数据,速度直接起飞:
// Download to a file - 这样改完速度会快很多 File outputFile = new File(downloadPath); try (FileOutputStream fileOutputStream = new FileOutputStream(outputFile)) { fileOutputStream.write(responseBytes); // 直接写整个字节数组 }
更优的进阶方案:跳过字节数组,直接流对流传
其实你还能进一步优化——没必要把整个文件先读到内存的字节数组里再写,尤其是大文件,这样既占内存又多了一步拷贝。直接把S3返回的输入流写到文件输出流,内存占用更低,速度也更快:
File outputFile = new File(downloadPath); // 直接把S3的响应流传输到文件输出流,不用先转成字节数组 try (FileOutputStream fileOutputStream = new FileOutputStream(outputFile); ResponseInputStream<GetObjectResponse> getResponse = s3Client.getObject(request)) { getResponse.transferTo(fileOutputStream); // JDK9+支持的方法,一步到位 }
如果你的JDK版本低于9,也可以用缓冲流的方式手动处理:
byte[] buffer = new byte[8192]; // 8KB缓冲是比较通用的大小,也可以试16KB/32KB int bytesRead; File outputFile = new File(downloadPath); try (FileOutputStream fileOutputStream = new FileOutputStream(outputFile); ResponseInputStream<GetObjectResponse> getResponse = s3Client.getObject(request)) { while ((bytesRead = getResponse.read(buffer)) != -1) { fileOutputStream.write(buffer, 0, bytesRead); } }
这种方式会把数据分成一个个缓冲块来读写,既减少了系统调用次数,又不会占用过多内存,处理超大文件也不用担心内存溢出。
总结一下
- 绝对不要逐个字节写文件,这是性能杀手
- 优先用批量写入的方式,要么写整个字节数组,要么用缓冲块
- 大文件场景下,直接用流对流传,跳过内存中的字节数组环节
备注:内容来源于stack exchange,提问作者Tim
相关产品推荐
相关产品推荐

