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或缓冲流,平衡代码可读性与性能。
相关推荐
guslegend3 天前
说说你对泛型的理解
大厂面试专题
guslegend10 天前
Java中变量和常量有什么区别
大厂面试专题
guslegend11 天前
String类能被继承吗,为什么
大厂面试专题
guslegend12 天前
HashMap和Hashtable有什么区别
大厂面试专题
guslegend18 天前
Java中止线程的三种方式
大厂面试专题
guslegend21 天前
提示词工程能够解决什么问题?
大厂面试专题
guslegend21 天前
缓存淘汰机制LRU和LFU的区别
大厂面试专题