Java 输入流到输出流的复制方法主要有以下六种实现方式,根据性能、适用场景和实现原理可分为不同类别:
一、基础字节流方式
实现原理:通过 FileInputStream
和 FileOutputStream
逐字节或块读取数据并写入。
代码示例:
try (InputStream in = new FileInputStream("source.txt");OutputStream out = new FileOutputStream("dest.txt")) {byte[] buffer = new byte[1024];int len;while ((len = in.read(buffer)) != -1) {out.write(buffer, 0, len);}
}
特点:实现简单但效率较低,适用于小文件。
二、缓冲流优化
实现原理:通过 BufferedInputStream
和 BufferedOutputStream
包装基础流,利用内存缓冲区减少 I/O 操作次数。
代码示例:
try (BufferedInputStream bis = new BufferedInputStream(new FileInputStream("source.txt"));BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("dest.txt"))) {byte[] buffer = new byte[8192];int len;while ((len = bis.read(buffer)) != -1) {bos.write(buffer, 0, len);}
}
特点:缓冲区(通常设为 8KB 以上)可提升 2-5 倍性能,适合中小文件。
三、NIO 通道零拷贝
实现原理:使用 FileChannel.transferTo()
或 transferFrom()
方法,直接调用操作系统的零拷贝技术(如 Linux 的 sendfile
)。
代码示例:
try (FileChannel inChannel = new FileInputStream("source.txt").getChannel();FileChannel outChannel = new FileOutputStream("dest.txt").getChannel()) {inChannel.transferTo(0, inChannel.size(), outChannel);
}
特点:数据在内核态直接传输,避免用户态内存拷贝,适合大文件(>100MB)。
四、Files.copy 工具方法
实现原理:通过 java.nio.file.Files
类的静态方法 copy()
实现,底层可能使用用户态循环或优化策略。
代码示例:
Path source = Paths.get("source.txt");
Path dest = Paths.get("dest.txt");
Files.copy(source, dest, StandardCopyOption.REPLACE_EXISTING);
特点:代码简洁,但性能略低于零拷贝,适合快速开发场景。
五、内存映射文件(MappedByteBuffer)
实现原理:通过 FileChannel.map()
将文件映射到内存地址,直接操作内存实现高效读写。
代码示例:
try (RandomAccessFile raf = new RandomAccessFile("source.txt", "r");FileChannel channel = raf.getChannel()) {MappedByteBuffer buffer = channel.map(FileChannel.MapMode.READ_ONLY, 0, channel.size());// 直接通过 buffer 操作数据并写入输出流
}
特点:适合超大文件(>1GB)的随机访问,但需注意内存管理风险。
六、第三方工具库
实现原理:使用 Apache Commons IO 的 FileUtils.copyFile()
封装底层流操作。
代码示例:
File source = new File("source.txt");
File dest = new File("dest.txt");
FileUtils.copyFile(source, dest);
特点:简化代码,但依赖外部库。
性能对比与选型建议
方法 | 性能排序 | 适用场景 | 引用来源 |
---|---|---|---|
NIO 通道零拷贝 | ★★★★★ | 大文件传输(>100MB) | |
内存映射文件 | ★★★★☆ | 超大文件随机访问 | |
缓冲流 | ★★★☆☆ | 中小文件通用场景 | |
Files.copy() | ★★☆☆☆ | 快速开发、小文件 | |
基础字节流 | ★☆☆☆☆ | 学习或极小型文件 |
扩展知识
- 零拷贝技术原理:通过
transferTo()
调用系统级函数(如sendfile
),跳过用户态缓冲区,减少 CPU 上下文切换。 - 缓冲区大小优化:建议缓冲区设为 8KB~1MB,过小会导致频繁系统调用,过大可能浪费内存。
- 堆外内存管理:使用
DirectByteBuffer
时需手动释放或依赖 JVM 的Cleaner
机制,避免内存泄漏。
实际开发中,优先选择 NIO 通道或缓冲流方案,第三方库可简化代码但需权衡依赖。