文章目录
- 一、Java文件拷贝的5种方式
- 1. 传统IO流(字节流/字符流)手动拷贝
- 2. NIO的`FileChannel`拷贝(`transferTo`/`transferFrom`)
- 3. Java 7+的`Files.copy()`工具类
- 4. 缓冲流(`BufferedInputStream`/`BufferedOutputStream`)
- 5. 第三方库(如Apache Commons IO)
- 二、效率对比与结论
- 各方式效率排序(从高到低):
- 为什么`FileChannel`效率最高?
- 注意事项:
- 总结
在Java中,文件拷贝是常见的IO操作,主要有以下几种实现方式,它们的效率因底层机制不同而有显著差异:
一、Java文件拷贝的5种方式
1. 传统IO流(字节流/字符流)手动拷贝
通过
FileInputStream
和FileOutputStream
逐字节或按缓冲区读取写入,是最基础的方式。
public static void copyWithStream(File source, File dest) throws IOException {try (InputStream in = new FileInputStream(source);OutputStream out = new FileOutputStream(dest)) {byte[] buffer = new byte[8192]; // 8KB缓冲区int bytesRead;while ((bytesRead = in.read(buffer)) != -1) {out.write(buffer, 0, bytesRead);}}
}
2. NIO的FileChannel
拷贝(transferTo
/transferFrom
)
基于NIO的通道(Channel)机制,通过
FileChannel
的transferTo
或transferFrom
方法实现拷贝,底层依赖操作系统的零拷贝(Zero-Copy)机制。
public static void copyWithChannel(File source, File dest) throws IOException {try (FileChannel inChannel = new FileInputStream(source).getChannel();FileChannel outChannel = new FileOutputStream(dest).getChannel()) {inChannel.transferTo(0, inChannel.size(), outChannel);}
}
3. Java 7+的Files.copy()
工具类
Java 7引入的
java.nio.file.Files
工具类,封装了拷贝逻辑,内部实际使用FileChannel
实现。
public static void copyWithFiles(File source, File dest) throws IOException {Files.copy(source.toPath(), dest.toPath());
}
4. 缓冲流(BufferedInputStream
/BufferedOutputStream
)
在传统字节流基础上增加缓冲区,减少IO次数(默认8KB缓冲区,可自定义大小)。
public static void copyWithBufferedStream(File source, File dest) throws IOException {try (BufferedInputStream in = new BufferedInputStream(new FileInputStream(source));BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(dest))) {byte[] buffer = new byte[8192];int bytesRead;while ((bytesRead = in.read(buffer)) != -1) {out.write(buffer, 0, bytesRead);}}
}
5. 第三方库(如Apache Commons IO)
借助第三方工具类(如
FileUtils.copyFile
),内部实现类似缓冲流,但简化了代码。
public static void copyWithCommonsIO(File source, File dest) throws IOException {FileUtils.copyFile(source, dest); // 需要引入commons-io依赖
}
二、效率对比与结论
各方式效率排序(从高到低):
- NIO
FileChannel
(transferTo
/transferFrom
)Files.copy()
(内部基于FileChannel
,效率接近)- 缓冲流(
BufferedInputStream
/BufferedOutputStream
)- 第三方库(如Apache Commons IO)(与缓冲流效率相当)
- 传统字节流手动拷贝(无缓冲,效率最低)
为什么FileChannel
效率最高?
- 零拷贝(Zero-Copy)机制:
transferTo
方法直接在操作系统内核空间完成数据传输,避免了Java堆内存与内核缓冲区之间的来回拷贝(用户态→内核态的切换减少)。- 减少IO次数:传统流需要多次系统调用(read→用户态→write→内核态),而
FileChannel
通过一次系统调用完成数据传输,尤其对大文件(GB级)优势明显。
注意事项:
- 小文件场景:各方式效率差异不大,
Files.copy()
因代码简洁更推荐。- 大文件场景:
FileChannel
的优势显著,拷贝速度可能是传统流的2-10倍。- 跨文件系统拷贝:若源文件和目标文件在不同文件系统,
transferTo
可能无法一次完成,需循环调用,但仍比传统流高效。
总结
效率最高的方式是使用NIO的
FileChannel.transferTo()
或transferFrom()
,尤其适合大文件拷贝。日常开发中,推荐使用Files.copy()
(Java 7+),它兼顾了效率与代码简洁性,底层同样依赖FileChannel
的零拷贝机制。