filesystemexception 不直接暴露 errno 或完整路径,但可通过 getfile()、getotherfile() 和 getreason() 安全获取路径与标准化错误原因;反射读取 errno 仅限调试,生产环境应封装调用并结合 getreason() 映射处理。

Java 的 FileSystemException 本身**不直接暴露操作系统底层的 errno(如 Linux 的 ENOENT、EACCES)或 Windows 的 Win32 错误码(如 ERROR_PATH_NOT_FOUND)**,也不保存原始路径变量(如 `path1`, `path2`)的完整上下文。但它通过继承自 IOException 的机制,**间接携带了这些信息**,关键在于正确提取和解析。
查看 getMessage() 中隐含的错误码与路径
多数 JDK 实现(尤其是 OpenJDK 和 HotSpot)在构造 FileSystemException 时,会将底层系统错误码(经本地方法转换)和路径拼入消息字符串。例如:
java.nio.file.FileSystemException: /tmp/readonly.txt: Permission denied
java.nio.file.FileSystemException: C:\missing\file.txt: The system cannot find the path specified.
虽然这不是结构化数据,但可通过正则提取路径和错误描述(注意:不可靠用于生产判断,仅作调试参考):
- 用
exception.getMessage()获取完整字符串 - 用
exception.getFile()获取主路径(JDK 7+ 提供,对应第一个路径参数) - 部分异常还支持
exception.getOtherFile()(如涉及两个路径的操作:move、copy)
利用 getReason() 获取标准化错误原因(推荐)
FileSystemException.getReason() 返回的是**平台无关的、简短的错误描述字符串**(如 "Permission denied", "No such file or directory"),它由 JVM 将底层 errno 映射而来,比 getMessage() 更稳定,是识别错误类型的首选方式:
-
"Permission denied"→ 对应 Linux 的 EACCES / Windows 的 ERROR_ACCESS_DENIED -
"No such file or directory"→ 对应 Linux 的 ENOENT / Windows 的 ERROR_PATH_NOT_FOUND -
"Directory not empty"→ 对应 Linux 的 ENOTEMPTY / Windows 的 ERROR_DIR_NOT_EMPTY
可据此做轻量级分类处理,无需解析原始消息。
通过反射获取私有 errno 字段(仅限调试,不推荐生产)
OpenJDK 源码中,UnixException(FileSystemException 的实际实现类之一)持有 errno 字段;Windows 下对应 WindowsException 持有 errorCode。可通过反射临时读取(仅限开发/诊断):
- 检查异常是否为
sun.nio.fs.UnixException或sun.nio.fs.WindowsException - 用
Field f = ex.getClass().getDeclaredField("errno")(Unix)或"errorCode"(Windows) - 调用
f.setAccessible(true)后获取值
⚠️ 注意:这是内部 API,不同 JDK 版本/厂商可能不存在或改名,**严禁用于生产环境**。
更可靠的做法:主动捕获并封装底层错误
若需稳定获取 errno 或完整路径上下文,建议在调用 NIO 方法前自行封装,例如:
- 使用
Files.exists(path, LinkOption.NOFOLLOW_LINKS)替代直接 open,避免触发异常 - 对关键操作(如 delete、move)加 try-catch,并在 catch 块中记录
ex.getFile()、ex.getOtherFile()和ex.getReason() - 结合
System.getProperty("os.name")判断平台,按需映射getReason()到标准 errno 名称(如构建映射表)
这样既避开反射风险,又能获得足够诊断信息。











