先从复制一个文件开始。Java NIO 不需要额外依赖,并能把不存在、权限不足和目标冲突作为异常报告。
可运行的单文件复制
保存为 CopyFileDemo.java,Java 8 以上可运行:
import java.nio.file.Files;import java.nio.file.Path;import java.nio.file.Paths;
public class CopyFileDemo { public static void main(String[] args) throws Exception { if (args.length != 2) { throw new IllegalArgumentException("用法:java CopyFileDemo 源文件 目标文件"); } Path source = Paths.get(args[0]).toRealPath(); Path target = Paths.get(args[1]).toAbsolutePath().normalize(); if (!Files.isRegularFile(source)) { throw new IllegalArgumentException("源路径必须是普通文件"); } if (Files.exists(target)) { throw new IllegalArgumentException("目标已存在,请换一个文件名"); } Files.createDirectories(target.getParent()); Files.copy(source, target); System.out.println("已复制 " + Files.size(target) + " 字节"); }}在 PowerShell 的空目录中运行:
'hello' | Set-Content -Encoding utf8 source.txtjavac -encoding UTF-8 CopyFileDemo.javajava CopyFileDemo source.txt output/copied.txtGet-FileHash source.txt, output/copied.txt两个哈希相同,说明文件内容一致;再次执行会拒绝覆盖。需要覆盖时才显式使用 StandardCopyOption.REPLACE_EXISTING,并先确认目标文件。
目录复制为什么不能直接照搬递归
目录复制还要确定符号链接、空目录、目标冲突和异常中断的处理。特别是把源目录复制到它自己的子目录时,递归可能不断复制新生成的内容。
实现目录工具前,先将源和目标转换为真实/规范路径,拒绝相同路径和源目录内的目标;明确是否跟随链接;使用 Files.walkFileTree 处理目录与文件,传播错误。复制不是备份事务,中途中断时目标可能只有部分内容,不能把“创建了目标目录”当成完成。
参考:Files API。
评论