cam*_*ecc 4 java filesystems zip jar nio2
我正在尝试找到一种简单的方法来将 a 映射URI
到 a Path
,而无需编写特定于任何特定文件系统的代码。以下似乎可行,但需要一种有问题的技术:
public void process(URI uri) throws IOException {
try {
// First try getting a path via existing file systems. (default fs)
Path path = Paths.get(uri);
doSomething(uri, path);
}
catch (FileSystemNotFoundException e) {
// No existing file system, so try creating one. (jars, zips, etc.)
Map<String, ?> env = Collections.emptyMap();
try (FileSystem fs = FileSystems.newFileSystem(uri, env)) {
Path path = fs.provider().getPath(uri); // yuck :(
// assert path.getFileSystem() == fs;
doSomething(uri, path);
}
}
}
private void doSomething(URI uri, Path path) {
FileSystem fs = path.getFileSystem();
System.out.println(uri);
System.out.println("[" + fs.getClass().getSimpleName() + "] " + path);
}
Run Code Online (Sandbox Code Playgroud)
在几个示例上运行此代码会产生以下结果:
file:/C:/Users/cambecc/target/classes/org/foo
[WindowsFileSystem] C:\Users\cambecc\target\classes\org\foo
jar:file:/C:/Users/cambecc/bin/utils-1.0.jar!/org/foo
[ZipFileSystem] /org/foo
Run Code Online (Sandbox Code Playgroud)
请注意 s 是如何URI
映射到Path
已“扎根”到正确类型的对象的FileSystem
,例如引用 jar 内目录“/org/foo”的 Path。
这段代码让我困扰的是,尽管 NIO2 可以很容易地:
Paths.get(URI)
FileSystem
实例: FileSystems.newFileSystem(uri, env)
...没有好的方法可以将 URI 映射到新 FileSystem
实例中的 Path。
我能找到的最好的办法是,创建文件系统后,我可以要求它FileSystemProvider
给我路径:
Path path = fs.provider().getPath(uri);
Run Code Online (Sandbox Code Playgroud)
但这似乎是错误的,因为不能保证它会返回绑定到我刚刚实例化的文件系统的路径(即path.getFileSystem() == fs
)。它很大程度上依赖于 FileSystemProvider 的内部状态来了解我所指的 FileSystem 实例。难道就没有更好的办法了吗?
您在 zipfs 的实现/文档中发现了一个错误。Path.get 方法的文档指出:
* @throws FileSystemNotFoundException
* The file system, identified by the URI, does not exist and
* cannot be created automatically
Run Code Online (Sandbox Code Playgroud)
编辑:对于需要关闭的文件系统,最好要求程序员调用 newFileSystem 以便他可以关闭它。该文档最好阅读“如果不应自动创建”。
ZipFs 从不尝试创建新的文件系统。失败的 get() 不会被捕获,而是在尝试 newFileSystem 调用之前传递给调用者。参见源码:
public Path getPath(URI uri) {
String spec = uri.getSchemeSpecificPart();
int sep = spec.indexOf("!/");
if (sep == -1)
throw new IllegalArgumentException("URI: "
+ uri
+ " does not contain path info ex. jar:file:/c:/foo.zip!/BAR");
return getFileSystem(uri).getPath(spec.substring(sep + 1));
}
Run Code Online (Sandbox Code Playgroud)
换句话说:
Paths.get()
Run Code Online (Sandbox Code Playgroud)
对于所有基于 nio2 的文件系统来说应该足够了。采用zipfs设计。
Path path;
try {
path = Paths.get( uri );
} catch ( FileSystemNotFoundException exp ) {
try( FileSystem fs = FileSystems.newFileSystem( uri, Collections.EMPTY_MAP )) {;
path = Paths.get( uri );
... use path ...
}
}
Run Code Online (Sandbox Code Playgroud)
是您的解决方法的简短形式。
注意:nio 文档指出 getFileSystem 必须使用/返回由匹配的 newFileSystem 创建的文件系统。
归档时间: |
|
查看次数: |
3077 次 |
最近记录: |