InvalidPathException 是路径构造时的预检异常,非运行时访问失败;它在 Paths.get() 调用时立即触发,反映字符串非法(如 Windows 禁用字符、控制字符、保留设备名),而非磁盘或权限问题。

InvalidPathException 不是运行时访问失败的信号,而是路径构造阶段的“提前叫停”——它在你调用 Paths.get() 的那一刻就触发,意味着问题出在字符串本身,而非磁盘或权限。这种预检机制本质是操作系统级约束的 Java 显式暴露,尤其在 Windows 上表现得最严格。
Windows 路径预检:哪些字符一出现就报错
Windows 下 Paths.get() 会主动拦截以下字符(除盘符后的冒号外):
-
:(如C: est:name.txt中的冒号) 、<code>>、|、?、*- 保留设备名,如
AUX、CON、PRN等作为文件名或目录名 - 不可见控制字符,如
u0000(空字符)、u0001,常来自剪贴板粘贴或 HTTP 参数污染
跨平台预检差异:Linux/macOS 不拦字符,但可能后续崩
Unix 类系统默认不校验 :、| 等符号,Paths.get("file:name.txt") 能成功构造 Path。但隐患藏在后面:
- 调用
path.toFile().exists()或Files.exists(path)时,底层stat()可能返回EINVAL - 某些 JDK 版本(如 OpenJDK 17+)会把该错误重新包装为
InvalidPathException,提示 “Malformed input or input contains unmappable characters” - 真正元凶往往是 UTF-8 解码失败或零字节,不是冒号本身
预检拦截的实用写法:清洗 + 尝试构造
不要等异常抛出再处理,应在构造前主动过滤。推荐组合策略:
- 先用
String.strip()去首尾空白 - 再用正则清除不可见控制字符:
.replaceAll("[\x00-\x08\x0b\x0c\x0e-\x1f]", "") - 对 Windows 兼容场景,替换非法字符:
.replaceAll("[\\/:*?"|]", "_") - 最后调用
Paths.get(),捕获InvalidPathException作兜底验证
关键避坑点:Paths.get() vs new File().toPath()
二者行为完全不同,混用极易漏检:
-
Paths.get("C:/a:b.txt")→ 直接抛InvalidPathException -
new File("C:/a:b.txt").toPath()→ 成功返回 Path,但后续Files.exists()很可能失败 - 统一使用
Paths.get(),它是唯一带预检语义的标准入口

















