java nio文件读写高性能关键在于合理组合channel与buffer:大文件用transferto/transferfrom零拷贝;gb级随机读写用mappedbytebuffer分段映射;中等文件用固定bytebuffer配合flip/clear;常用操作优先使用files工具类。

Java NIO 的文件读写高性能,关键不在“用不用 Channel 和 Buffer”,而在于“怎么组合用”——避开系统调用开销、减少内存拷贝、匹配场景选对模式。
优先用 transferTo / transferFrom 做零拷贝复制
这是大文件(如日志归档、安装包分发)最省力的方式。Linux 下直接调用 sendfile(),数据全程在内核态搬运,不进 JVM 堆,也不触发用户态内存拷贝。
- 只适用于文件到文件、文件到 SocketChannel 场景;FileChannel 之间不能直接 transfer,需借助中间通道(如 Pipe 或 Socket)
- 单次 transferTo 最多处理约 2GB(
Integer.MAX_VALUE字节),超大文件必须循环调用 - 源通道需为
READ模式,目标通道需为WRITE模式,且目标文件需提前创建或带CREATE选项
超大文件随机读写就用内存映射(MappedByteBuffer)
适合 GB 级日志分析、数据库快照加载等需要频繁跳转读取的场景。映射后访问就像操作数组,免去 read() 调用和缓冲区填充开销。
- 映射区域大小不能超过
Integer.MAX_VALUE(约 2GB),超大文件要分段 map,例如每 1GB 映射一次 - 只读用
FileChannel.MapMode.READ_ONLY,读写用READ_WRITE;慎用PRIVATE(写时拷贝,内存占用翻倍) - JDK 9+ 推荐用
Cleaner清理映射;JDK 8 需反射调用sun.misc.Cleaner的clean()方法,否则可能引发内存泄漏
中等文件或需解析内容时,用固定 ByteBuffer + flip/clear 流程
比如逐行处理 CSV、解析 JSON 片段、做文本替换等,需要控制数据边界和内容逻辑,这时标准 buffer 流程更可控、更安全。
- 缓冲区大小建议设为 64KB–1MB:太小导致 read() 调用频繁;太大浪费堆内存或堆外内存
- 每次
read()后必须flip()切换读模式;读完用clear()(非compact())重置位置,准备下一轮写入 - 避免调用
buffer.array()直接获取底层字节数组——可能抛ReadOnlyBufferException,也破坏封装性
善用 Files 工具类简化常见操作
别总手动 open/close FileChannel。Files 提供了简洁、健壮的封装,底层仍是 NIO,还自动处理资源关闭、异常传播和路径解析。
-
Files.copy(src, dst, StandardCopyOption.REPLACE_EXISTING)→ 底层自动选最优 transfer 或 buffer 方式 -
Files.readAllBytes(path)和Files.write(path, bytes)→ 适合小文件,代码极简 -
Files.lines(path)返回 Stream→ 支持函数式处理,内部用 MappedByteBuffer 或高效 buffer 分块读取
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











