Java五种文件拷贝方式
- 在Java中,文件拷贝主要有以下几种方式,不同场景下效率差异显著;
- 以下从实现方式,效率对比和适用场景三方面详情解析。
文件拷贝的5种实现方式
1.传统字节流(FileInputStream+FileOutputStream)
java
/**
* 传统字节流(FileInputStream+FileOutputStream)
* @throws IOException
*/
public static void copy1() throws IOException{
String sourcePath = "C:\\Users\\Administrator\\Desktop\\interview\\Code\\src\\main\\resources\\source.txt";
String targetPath = "C:\\Users\\Administrator\\Desktop\\interview\\Code\\src\\main\\resources\\target.txt";
InputStream inputStream = new FileInputStream(sourcePath);
OutputStream outputStream = new FileOutputStream(targetPath);
byte[] buffer = new byte[1024];
int length;
while ((length = inputStream.read(buffer)) >0) {
outputStream.write(buffer, 0, length);
}
}
- 特点:基础方式,直接逐字节或缓冲区读写;
- 效率:最低(适合小文件)。
2.缓冲流优化拷贝(BufferedInputStream+BufferedOutputStream)
java
/**
* 缓冲流优化拷贝(BufferedInputStream+BufferedOutputStream)
* @throws IOException
*/
public static void copy2() throws IOException{
String sourcePath = "C:\\Users\\Administrator\\Desktop\\interview\\Code\\src\\main\\resources\\source.txt";
String targetPath = "C:\\Users\\Administrator\\Desktop\\interview\\Code\\src\\main\\resources\\target.txt";
BufferedInputStream inputStream = new BufferedInputStream(new FileInputStream(sourcePath));
BufferedOutputStream outputStream = new BufferedOutputStream(new FileOutputStream(targetPath));
byte[] buffer = new byte[8192];//缓冲区大小,缓冲区越大,性能越好(通常8KB~64KB)
int length;
while ((length = inputStream.read(buffer)) >0) {
outputStream.write(buffer, 0, length);
}
}
- 特点:通过减少缓冲区I/O次数;
- 效率:比传统字节流提升2~5倍。
3.NIO Files.copy(Java7+)
java
/**
* NIO Files.copy(Java7+)
* @throws IOException
*/
public static void copy3() throws IOException{
String sourcePath = "C:\\Users\\Administrator\\Desktop\\interview\\Code\\src\\main\\resources\\source.txt";
String targetPath = "C:\\Users\\Administrator\\Desktop\\interview\\Code\\src\\main\\resources\\target.txt";
Files.copy(new File(sourcePath).toPath(), new File(targetPath).toPath());
}
- 特点:单行代码完成拷贝,底层自动优化;
- 效率:接近最高效(适合大多数场景)。
4.NIO FileChannel通道拷贝
java
/**
* NIO Files.copy(Java7+)
* @throws IOException
*/
public static void copy4() throws IOException{
String sourcePath = "C:\\Users\\Administrator\\Desktop\\interview\\Code\\src\\main\\resources\\source.txt";
String targetPath = "C:\\Users\\Administrator\\Desktop\\interview\\Code\\src\\main\\resources\\target.txt";
FileChannel sourceChannel = new FileInputStream(sourcePath).getChannel();
FileChannel targetChannel = new FileOutputStream(targetPath).getChannel();
sourceChannel.transferTo(0, sourceChannel.size(), targetChannel);
}
- 特点:利用通道(Channel)直接传输数据;
- 效率:大文件性能最佳(利用零拷贝技术)。
5.内存映射文件拷贝(MappedByBuffer)
java
/**
* 内存映射文件拷贝(MappedByBuffer)
* @throws IOException
*/
public static void copy5() throws IOException{
String sourcePath = "C:\\Users\\Administrator\\Desktop\\interview\\Code\\src\\main\\resources\\source.txt";
String targetPath = "C:\\Users\\Administrator\\Desktop\\interview\\Code\\src\\main\\resources\\target.txt";
RandomAccessFile sourceChannel = new RandomAccessFile(sourcePath, "r");
RandomAccessFile targetChannel = new RandomAccessFile(targetPath, "rw");
FileChannel channel = targetChannel.getChannel();
MappedByteBuffer mappedByteBuffer = sourceChannel.map(FileChannel.MapMode.READ_ONLY, 0, sourceChannel.size());
targetChannel.getChannel().write(mappedByteBuffer);
}
- 特点:将文件映射到内存中直接操作;
- 效率:适合超大文件(但实现复杂,需要谨慎处理内存)。
效率对比(1GB文件测试)
| 方法 | 耗时(毫秒) | 适用场景 |
|---|---|---|
| 传统字节流 | 4500~5000 | 小文件(<10MB) |
| 缓冲流 | 1200~1500 | 通用场景 |
Files.copy |
800~1000 | 简单代码 + 快速开发 |
FileChannel.transfer |
600~800 | 大文件(>100MB) |
| 内存映射文件 | 500~700 | 超大文件(>1GB) |
如何选择最高效的方式
- 小文件(<10MB):直接使用File.copy,代码简洁且性能足够;
- 大文件(100MB~1GB):优先选择FileChannel.transferTo(),利用零拷贝减少内核态与用户态数据复制;
- 超大文件(>1GB): 用内容映射文件(MappedByteBuffer)
- 但需要注意避免频繁映射/释放资源(开销大);
- 处理内容溢出风险(OutOfMemeory)。
- 通用场景:File.copy或缓冲流,平衡代码可读性与性能。