file.exists() 必须先于 isfile()/isdirectory() 调用,否则无法区分“不存在”和“非文件”;createnewfile() 需检查返回值并确保父目录存在;renameto() 跨文件系统必失败,应改用 files.move();路径比较必须用 getcanonicalpath()。

File.exists() 和 File.isFile()/isDirectory() 的判断顺序很重要
很多同学一上来就调用 File.isFile(),结果返回 false 却没意识到文件根本不存在——isFile() 和 isDirectory() 在文件不存在时一律返回 false,不抛异常,也不提示。
- 务必先用
exists()确认路径存在,再判断类型 - 如果只关心“是不是普通文件”,写成
file.exists() && file.isFile()更安全 - 注意:
exists()对符号链接会尝试解析目标;若目标不可达,可能返回false(取决于 OS 和权限)
createNewFile() 失败却不报错?检查返回值和异常场景
createNewFile() 是个“哑巴”方法:成功返回 true,已存在或失败都返回 false,且只在严重问题(如磁盘满、无权限)时才抛 IOException。光看返回值容易误判。
- 必须检查返回值:
if (!file.createNewFile()) { /* 可能已存在,也可能创建失败 */ } - 常见静默失败原因:父目录不存在(
createNewFile()不自动创建上级路径)、路径含非法字符、NTFS 重解析点干扰 - 更健壮的做法:先用
file.getParentFile().mkdirs()确保目录存在,再调createNewFile()
renameTo() 跨文件系统一定失败,别硬扛
renameTo() 在 Windows 上跨盘符(如 C: → D:)、Linux 上跨挂载点(如 /home → /mnt/usb)时直接返回 false,不抛异常,也不提示原因。
- 它本质是 OS 的
rename()系统调用,仅支持同文件系统内的原子重命名 - 跨卷操作需手动 copy + delete:用
Files.copy()+Files.delete()(推荐 Java 7+ 的StandardCopyOption.REPLACE_EXISTING) - 注意:旧版
File.renameTo()对中文路径在某些 JVM 版本上有编码兼容问题,建议统一用Path+Files.move()
getAbsolutePath() vs getCanonicalPath() —— 路径“真实身份”得靠后者
getAbsolutePath() 只是拼接当前工作目录和相对路径,不解析 .. 或符号链接;而 getCanonicalPath() 会真正访问文件系统,展开所有跳转,得到唯一、可比较的路径字符串。
立即学习“Java免费学习笔记(深入)”;
- 做路径相等判断(比如缓存 key、白名单校验)必须用
getCanonicalPath(),否则/a/../b和/b会被当成两个不同路径 -
getCanonicalPath()可能抛IOException(如路径中间某级不存在、权限不足),需 try-catch - 注意:Windows 下大小写不敏感,但
getCanonicalPath()返回的大小写取决于磁盘上实际存储形式,不要依赖其大小写一致性
事情说清了就结束。Java 的 File 类表面简单,但每个 API 背后都连着操作系统语义,尤其跨平台时,看似“应该能行”的操作往往卡在路径解析、权限模型或文件系统边界上。










