Java五种文件拷贝方式

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)

如何选择最高效的方式

  1. 小文件(<10MB):直接使用File.copy,代码简洁且性能足够;
  2. 大文件(100MB~1GB):优先选择FileChannel.transferTo(),利用零拷贝减少内核态与用户态数据复制;
  3. 超大文件(>1GB): 用内容映射文件(MappedByteBuffer)
    1. 但需要注意避免频繁映射/释放资源(开销大);
    2. 处理内容溢出风险(OutOfMemeory)。
  4. 通用场景:File.copy或缓冲流,平衡代码可读性与性能。
相关推荐
guslegend18 天前
说说你对设计模式的理解
大厂面试专题
guslegend18 天前
设计模式是如何分类的
大厂面试专题
guslegend23 天前
说说你对泛型的理解
大厂面试专题
guslegend1 个月前
Java中变量和常量有什么区别
大厂面试专题
guslegend1 个月前
String类能被继承吗,为什么
大厂面试专题
guslegend1 个月前
HashMap和Hashtable有什么区别
大厂面试专题
guslegend1 个月前
Java中止线程的三种方式
大厂面试专题
guslegend1 个月前
提示词工程能够解决什么问题?
大厂面试专题
guslegend1 个月前
缓存淘汰机制LRU和LFU的区别
大厂面试专题