Java中复制大文件首选FileChannel.transferTo()实现零拷贝,超2GB需分段循环搬运;次选Files.copy()自动优化路径,兼顾简洁与健壮性。

Java 中用 NIO 快速复制大型文件,核心是绕过用户态缓冲、减少数据拷贝次数,直接借助操作系统级的零拷贝能力。关键不在于“写得多”,而在于“让内核多干活、让 JVM 少搬数据”。
优先用 FileChannel.transferTo() 实现零拷贝
这是对大文件(尤其单个 >100MB)最有效的方案,底层在 Linux 调用 sendfile(),Windows 上也尽量复用系统优化路径。
- 源通道必须是
FileInputStream.getChannel()或RandomAccessFile("r").getChannel() - 目标通道必须是
FileOutputStream.getChannel()或RandomAccessFile("rw").getChannel() - 单次调用最大支持约 2GB;超大文件需分段处理(见下文)
处理超过 2GB 的文件要手动分段
transferTo() 在某些 JVM/OS 组合下对单次传输长度有限制(如 Integer.MAX_VALUE 字节),直接传 size() 可能截断。稳妥做法是循环搬运:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 计算剩余字节数
left = size - 每次最多传
2GB - 1(即0x7FFFFFFF)字节 - 更新 position:每次传完后
position += transferred
更简洁且健壮的替代:用 Files.copy() + 标准选项
如果不需要极致压榨性能,JDK 7+ 的 Files.copy() 是首选——它内部已自动选择最优路径(小文件走缓冲流,大文件倾向 channel 优化):
立即学习“Java免费学习笔记(深入)”;
- 支持原子性覆盖:
StandardCopyOption.REPLACE_EXISTING - 保留时间戳、权限等元数据:
StandardCopyOption.COPY_ATTRIBUTES - 自动处理资源关闭,无手动 close 风险
避免常见陷阱
不是所有“NIO 写法”都高效。以下操作反而会拖慢速度:
- 用
ByteBuffer.allocateDirect()+read()/write()手动搬数据——失去零拷贝优势,还增加 GC 压力 - 对小文件(transferTo——启动开销可能反超收益
- 未用 try-with-resources 或未显式 close Channel——导致文件句柄泄漏,后续复制失败

















