Java有几种文件拷贝方式,哪一种效率最高?

文章目录

在Java中,文件拷贝是常见的IO操作,主要有以下几种实现方式,它们的效率因底层机制不同而有显著差异:

一、Java文件拷贝的5种方式

1. 传统IO流(字节流/字符流)手动拷贝

通过FileInputStreamFileOutputStream逐字节或按缓冲区读取写入,是最基础的方式。

java 复制代码
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)机制,通过FileChanneltransferTotransferFrom方法实现拷贝,底层依赖操作系统的零拷贝(Zero-Copy)机制。

java 复制代码
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实现。

java 复制代码
public static void copyWithFiles(File source, File dest) throws IOException {
    Files.copy(source.toPath(), dest.toPath());
}
4. 缓冲流(BufferedInputStream/BufferedOutputStream

在传统字节流基础上增加缓冲区,减少IO次数(默认8KB缓冲区,可自定义大小)。

java 复制代码
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),内部实现类似缓冲流,但简化了代码。

java 复制代码
public static void copyWithCommonsIO(File source, File dest) throws IOException {
    FileUtils.copyFile(source, dest); // 需要引入commons-io依赖
}

二、效率对比与结论

各方式效率排序(从高到低):
  1. NIO FileChanneltransferTo/transferFrom
  2. Files.copy() (内部基于FileChannel,效率接近)
  3. 缓冲流(BufferedInputStream/BufferedOutputStream
  4. 第三方库(如Apache Commons IO)(与缓冲流效率相当)
  5. 传统字节流手动拷贝(无缓冲,效率最低)
为什么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的零拷贝机制。