
Java 文件移动前必须检查目标目录是否存在
很多同学直接用 Files.move() 把文件扔过去,结果抛出 java.nio.file.NoSuchFileException —— 不是因为源文件找不到,而是目标父目录压根没创建。Java 不会自动创建中间路径,这点和 Python 的 shutil.move() 行为不同。
- 先调用
Files.createDirectories(path.getParent())确保目标路径可写 - 别依赖
StandardCopyOption.REPLACE_EXISTING来“兜底”:它只覆盖同名文件,不解决目录缺失问题 - 如果目标是归档到
./archive/2024/06/这种带年月的路径,得手动解析日期、拼路径、再创建
按文件扩展名分类时别硬编码字符串匹配
用 fileName.endsWith(".jpg") 看似简单,但会漏掉 .JPG、.Jpeg,甚至隐藏扩展名如 .DS_Store(macOS)或带版本号的 .log.1。真实场景里扩展名大小写混杂、带点号的伪扩展名很常见。
- 统一转小写再比对:
fileName.toLowerCase().endsWith(".pdf") - 优先用
Files.probeContentType(path)做 MIME 类型探测(适合图片/文档等),但注意它在 Windows 上可能返回null,需 fallback 到扩展名 - 把分类规则抽成 Map
,比如 Map.of("image", Paths.get("images"), "doc", Paths.get("docs")),避免 if-else 堆砌
移动大文件时要加 try-with-resources 防止句柄泄漏
虽然 Files.move() 是原子操作,但底层仍涉及系统级文件句柄。如果批量处理几百个文件且中途异常退出,未关闭的输入流或临时锁可能导致后续操作失败(尤其在 Windows 上报 AccessDeniedException)。
技术上面应用了三层结构,AJAX框架,URL重写等基础的开发。并用了动软的代码生成器及数据访问类,加进了一些自己用到的小功能,算是整理了一些自己的操作类。系统设计上面说不出用什么模式,大体设计是后台分两级分类,设置好一级之后,再设置二级并选择栏目类型,如内容,列表,上传文件,新窗口等。这样就可以生成无限多个二级分类,也就是网站栏目。对于扩展性来说,如果有新的需求可以直接加一个栏目类型并新加功能操作
- 不用
FileInputStream/FileOutputStream手动复制——这是归档(copy+delete)而非移动,效率低且易出错 - 确保每个
Files.move()调用都在独立 try-catch 中,捕获IOException并记录原路径,避免静默跳过 - 如果要做“移动失败则重试 3 次”,记得每次重试前 sleep 100ms,给系统释放锁的时间
Windows 下中文路径乱码或拒绝访问的根源
不是 Java 编码问题,而是 Windows 文件系统权限 + 防病毒软件拦截双重作用。你看到的 AccessDeniedException 很可能不是权限不足,而是某安全软件正在扫描该文件,锁住了句柄。
立即学习“Java免费学习笔记(深入)”;
- 启动 JVM 时加参数
-Dfile.encoding=UTF-8,但重点不在这里;真正要查的是目标路径是否在 OneDrive/腾讯微云/360保险箱 同步目录内 - 用
Files.isWritable(targetParent)提前校验,比直接 move 更早暴露问题 - 遇到拒绝访问,先尝试用
ProcessBuilder调用cmd /c echo.写入同目录空文件,确认基础写权限是否正常
归档逻辑越简单越可靠:移动 ≠ 重命名 ≠ 压缩。先确保单个文件能稳稳落到目标目录,再叠加时间戳重命名、ZIP 打包这些附加动作。跨磁盘移动(比如 C 盘到 D 盘)本质是 copy+delete,速度慢且不可逆,动手前务必确认磁盘空间和备份状态。









