讲师中心 微信公众号
AI工具推荐 视频效率加速

在Java中如何实现文件拷贝工具_JavaIO流实战案例解析

落婷同学_4041

落婷同学_4041

发布时间:2026-01-19 06:35:34

|

577人浏览过

|

来源于php中文网

原创

推荐直接用 Files.copy(),它底层自动选择最优通道,比手写流更快更安全;需显式指定 REPLACE_EXISTING 避免异常,并注意符号链接处理。

在java中如何实现文件拷贝工具_javaio流实战案例解析

用 Files.copy() 最快最安全

Java 7+ 推荐直接用 Files.copy(),它底层自动选择最优通道(如 FileChannel 或零拷贝系统调用),比手写 BufferedInputStream + BufferedOutputStream 更快、更少出错。

常见错误是忽略 StandardCopyOption.REPLACE_EXISTING 导致目标文件已存在时抛 FileAlreadyExistsException;还有忘记处理符号链接(默认会复制链接本身,不是目标内容)。

  • 必须显式指定 StandardCopyOption.REPLACE_EXISTING 才能覆盖
  • 若需跟随符号链接,加 StandardCopyOption.COPY_ATTRIBUTES 不够,得先用 Files.readSymbolicLink() 判断再处理
  • 大文件(>1GB)下,Files.copy() 仍可能触发 GC 压力,此时可考虑分块 transferTo()
Path source = Paths.get("a.txt");
Path target = Paths.get("b.txt");
try {
    Files.copy(source, target, StandardCopyOption.REPLACE_EXISTING);
} catch (IOException e) {
    // 处理权限不足、磁盘满等
}

手动流拷贝时别漏掉 flush() 和 close()

用 FileInputStream / FileOutputStream 配合 BufferedInputStream / BufferedOutputStream 是 Java 6 兼容方案,但极易因忘记 flush() 或异常路径下未 close() 导致数据截断或句柄泄漏。

缓冲区大小不是越大越好:设为 8192(8KB)是多数场景的平衡点;超过 64KB 可能反而降低小文件性能(内存预分配开销)。

立即学习“Java免费学习笔记(深入)”;

每天工作结束后,一键生成当日所有 Git 仓库的提交日报,支持多仓库扫描
每天工作结束后,一键生成当日所有 Git 仓库的提交日报,支持多仓库扫描

Git 提交日报助手,自动扫描当天(含次日凌晨6点前)所有仓库的 commit,生成结构化日报。

下载
  • 必须用 try-with-resources,不能只靠 finally 中 close()
  • BufferedOutputStream 的 write() 不保证立即落盘,flush() 必须在 close() 前显式调用(虽然 close() 会隐式 flush,但异常中断时可能跳过)
  • 避免用 available() 判断 EOF——它返回的是“当前可无阻塞读取的字节数”,不是文件总长
try (InputStream in = new BufferedInputStream(new FileInputStream("src"));
     OutputStream out = new BufferedOutputStream(new FileOutputStream("dst"))) {
    byte[] buf = new byte[8192];
    int len;
    while ((len = in.read(buf)) != -1) {
        out.write(buf, 0, len);
    }
    out.flush(); // 显式 flush 更稳妥
}

FileChannel.transferTo() 适合超大文件但有平台限制

当拷贝 >500MB 文件且需要极致性能时,FileChannel.transferTo() 可利用操作系统零拷贝能力(如 Linux 的 sendfile),绕过 JVM 堆内存,大幅减少 CPU 和 GC 开销。

但它有两个硬伤:Windows 下单次 transfer 不能超过 2GB(int 参数限制),且某些旧版 JDK 在 ext4 文件系统上对稀疏文件支持不完整,可能拷出全零填充。

  • 必须确保源 channel 是 FileChannel(FileInputStream.getChannel()),目标 channel 也得是 FileChannel
  • 循环调用 transferTo(),每次传最多 Integer.MAX_VALUE 字节(约 2GB)
  • 不能用于网络 socket 输出流——transferTo() 第二参数只接受 WritableByteChannel,而 socket channel 不一定支持
try (FileChannel in = new FileInputStream("src").getChannel();
     FileChannel out = new FileOutputStream("dst").getChannel()) {
    long pos = 0;
    long count = in.size();
    while (pos < count) {
        pos += in.transferTo(pos, Math.min(count - pos, Integer.MAX_VALUE), out);
    }
}

复制目录不能只靠 Files.copy()

Files.copy() 默认只处理单个文件,对目录会直接抛 IOException(提示 “Is a directory”)。递归复制目录必须自己遍历,且要注意:符号链接、权限位、最后修改时间这些元数据不会自动继承。

最容易被忽略的是 Windows 下的只读文件——Files.copy() 失败后,目标目录可能已建好但里面空空如也,后续逻辑误判为“复制成功”。

  • 用 Files.walkFileTree() 配合 SimpleFileVisitor 是标准解法
  • 复制前先用 Files.setAttribute() 设置目标目录权限("posix:permissions" 或 "dos:readonly")
  • 用 Files.getLastModifiedTime() 和 Files.setLastModifiedTime() 同步时间戳

复杂点在于:有些场景要跳过特定子目录(如 .git),有些要保留硬链接一致性——这些都得在 visitFile() 和 preVisitDirectory() 里手动控制。

热门AI工具

更多
WorkBuddy

一款AI办公效率工具,主要用于腾讯云推出的AI原生桌面智能体工作台,适合需要提升相关任务效率的用户。

讯飞智作

讯飞智作是一款AI视频创作工具,AI文本配音工具,数字人课程、营销视频制作。

DeepSeek

DeepSeek是一款面向对话、写作、编程和推理场景的AI大模型工具。

咔片AIPPT

一款在线AI演示文稿制作工具,可根据主题和内容需求辅助生成PPT结构与页面,提高演示材料制作效率。

UpDream
UpDream Hot

一款AI视频创作工具,主要用于哔哩哔哩推出的自研AI视频创作工具,适合需要提升相关任务效率的用户。

Laper
Laper Hot

Laper是专为编剧、导演和制片人推出的 AI 原生剧本创作工具。

VibeKnow
VibeKnow Hot

一款AI视频创作工具,主要用于全球首个AI知识视频创作平台,文档、文章、网页,一键生成视频,适合需要提升相关任务效率的用户。

豆包大模型

豆包大模型是一款由字节跳动推出的企业级大语言模型服务平台。

切问学术

切问学术是一款AI论文写作工具,复旦大学NLP团队推出的AI学术智能体。

相关专题

更多
string转int
string转int

在编程中,我们经常会遇到需要将字符串(str)转换为整数(int)的情况。这可能是因为我们需要对字符串进行数值计算,或者需要将用户输入的字符串转换为整数进行处理。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

6379

2023.08.02

int占多少字节
int占多少字节

int占4个字节,意味着一个int变量可以存储范围在-2,147,483,648到2,147,483,647之间的整数值,在某些情况下也可能是2个字节或8个字节,int是一种常用的数据类型,用于表示整数,需要根据具体情况选择合适的数据类型,以确保程序的正确性和性能。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

3085

2024.08.29

c++怎么把double转成int
c++怎么把double转成int

本专题整合了 c++ double相关教程,阅读专题下面的文章了解更多详细内容。

3988

2025.08.29

C++中int的含义
C++中int的含义

本专题整合了C++中int相关内容,阅读专题下面的文章了解更多详细内容。

2765

2025.08.29

堆和栈的区别
堆和栈的区别

堆和栈的区别:1、内存分配方式不同;2、大小不同;3、数据访问方式不同;4、数据的生命周期。本专题为大家提供堆和栈的区别的相关的文章、下载、课程内容,供大家免费下载体验。

5827

2023.07.18

堆和栈区别
堆和栈区别

堆(Heap)和栈(Stack)是计算机中两种常见的内存分配机制。它们在内存管理的方式、分配方式以及使用场景上有很大的区别。本文将详细介绍堆和栈的特点、区别以及各自的使用场景。php中文网给大家带来了相关的教程以及文章欢迎大家前来学习阅读。

2508

2023.08.10

Golang channel原理
Golang channel原理

本专题整合了Golang channel通信相关介绍,阅读专题下面的文章了解更多详细内容。

454

2025.11.14

golang channel相关教程
golang channel相关教程

本专题整合了golang处理channel相关教程,阅读专题下面的文章了解更多详细内容。

619

2025.11.17

OpenJDK JVM参数怎么调优
OpenJDK JVM参数怎么调优

Java应用运行缓慢,如何调整JVM参数?本专题介绍OpenJDK JVM性能调优的基本流程,涵盖性能指标确认、运行数据采集、内存配置和垃圾回收分析,帮助你先定位瓶颈,再通过对照测试验证效果,避免直接套用参数而影响应用稳定性。

80

2026.10.16

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Python uv官方安装与入门文档
Python uv官方安装与入门文档

共0课时 | 0人学习

Buffalo框架快速入门指南
Buffalo框架快速入门指南

共0课时 | 0人学习

Valgrind支持平台说明
Valgrind支持平台说明

共0课时 | 0人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn