如何通过java.nio.file.FileSystems.getDefault()方法获取本机文件系统实例?
- 内容介绍
- 文章标签
- 相关推荐
本文共计757个文字,预计阅读时间需要4分钟。
javapublic class FileSystemExample { public static void main(String[] args) { FileSystem fs=FileSystems.getDefault(); System.out.println(fs); }}
它的行为严格受限于当前运行环境:不能跨平台复用,不能切换根路径,也不能通过它访问 jar 内部、网络路径或内存文件系统(除非显式注册了对应 provider)。
为什么不能用它读取 JAR 包里的资源
常见误区是以为 FileSystems.getDefault() 能访问 jar:file:///xxx.jar!/path/ 这类 URI —— 它做不到。JAR 文件系统由 jar scheme 的 provider 提供,必须显式调用 FileSystems.newFileSystem(URI, env) 才能加载。
-
FileSystems.getDefault().getPath("jar:file:/a.jar!/META-INF/MANIFEST.MF")会抛出InvalidPathException - 即使路径语法合法(如
/tmp/test.txt),若该路径实际在 ZIP/JAR 中,getDefault()仍无法解析其内容 - JDK 不会在启动时自动注册非默认 provider,
getDefault()永远只认本地磁盘路径
获取后怎么安全使用 getPath() 和 isSupported() 方法
拿到 FileSystem 实例后,别直接假设所有方法都可用。不同 OS 的实现支持能力不同,尤其涉及符号链接、文件属性、ACL 等特性时。
立即学习“Java免费学习笔记(深入)”;
- 用
fs.supportedFileAttributeViews()查看支持哪些视图(如"basic","dos","posix"),Windows 上"posix"总是返回空列表 -
fs.getPath()接收的是字符串路径,不校验是否存在,也不做路径规范化(比如"a/../b"不会自动转成"b"),需自行调用toRealPath()或normalize() - 避免在 Windows 上对路径使用
Files.readAttributes(path, PosixFileAttributes.class),会抛UnsupportedOperationException
替代方案:什么时候不该用 getDefault()
当需求超出本地磁盘文件操作时,getDefault() 就是错的选择。典型场景包括:
- 需要统一处理 classpath 下的资源(含 JAR 内文件)→ 改用
Class.getResourceAsStream()或ClassLoader.getResources() - 要遍历 ZIP/JAR 包内容 → 必须用
FileSystems.newFileSystem(Paths.get("a.jar"), Collections.emptyMap()) - 测试中模拟文件系统行为 → 使用
MemoryFileSystemBuilder(第三方)或JimFS,而非试图 mockgetDefault() - 需要挂载网络路径(如 SMB/NFS)→ JDK 原生不支持,得依赖 OS 挂载点 +
getDefault()访问挂载后的本地路径
最常被忽略的一点:多个线程共享同一个 getDefault() 实例是安全的,但它内部缓存的 Path 实例不是线程安全的 —— 别把 fs.getPath(...) 的结果缓存为静态变量并在多线程间传递修改。
本文共计757个文字,预计阅读时间需要4分钟。
javapublic class FileSystemExample { public static void main(String[] args) { FileSystem fs=FileSystems.getDefault(); System.out.println(fs); }}
它的行为严格受限于当前运行环境:不能跨平台复用,不能切换根路径,也不能通过它访问 jar 内部、网络路径或内存文件系统(除非显式注册了对应 provider)。
为什么不能用它读取 JAR 包里的资源
常见误区是以为 FileSystems.getDefault() 能访问 jar:file:///xxx.jar!/path/ 这类 URI —— 它做不到。JAR 文件系统由 jar scheme 的 provider 提供,必须显式调用 FileSystems.newFileSystem(URI, env) 才能加载。
-
FileSystems.getDefault().getPath("jar:file:/a.jar!/META-INF/MANIFEST.MF")会抛出InvalidPathException - 即使路径语法合法(如
/tmp/test.txt),若该路径实际在 ZIP/JAR 中,getDefault()仍无法解析其内容 - JDK 不会在启动时自动注册非默认 provider,
getDefault()永远只认本地磁盘路径
获取后怎么安全使用 getPath() 和 isSupported() 方法
拿到 FileSystem 实例后,别直接假设所有方法都可用。不同 OS 的实现支持能力不同,尤其涉及符号链接、文件属性、ACL 等特性时。
立即学习“Java免费学习笔记(深入)”;
- 用
fs.supportedFileAttributeViews()查看支持哪些视图(如"basic","dos","posix"),Windows 上"posix"总是返回空列表 -
fs.getPath()接收的是字符串路径,不校验是否存在,也不做路径规范化(比如"a/../b"不会自动转成"b"),需自行调用toRealPath()或normalize() - 避免在 Windows 上对路径使用
Files.readAttributes(path, PosixFileAttributes.class),会抛UnsupportedOperationException
替代方案:什么时候不该用 getDefault()
当需求超出本地磁盘文件操作时,getDefault() 就是错的选择。典型场景包括:
- 需要统一处理 classpath 下的资源(含 JAR 内文件)→ 改用
Class.getResourceAsStream()或ClassLoader.getResources() - 要遍历 ZIP/JAR 包内容 → 必须用
FileSystems.newFileSystem(Paths.get("a.jar"), Collections.emptyMap()) - 测试中模拟文件系统行为 → 使用
MemoryFileSystemBuilder(第三方)或JimFS,而非试图 mockgetDefault() - 需要挂载网络路径(如 SMB/NFS)→ JDK 原生不支持,得依赖 OS 挂载点 +
getDefault()访问挂载后的本地路径
最常被忽略的一点:多个线程共享同一个 getDefault() 实例是安全的,但它内部缓存的 Path 实例不是线程安全的 —— 别把 fs.getPath(...) 的结果缓存为静态变量并在多线程间传递修改。

