NIO2:如何一般地将URI映射到路径? [英] NIO2: how to generically map a URI to a Path?

查看:204
本文介绍了NIO2:如何一般地将URI映射到路径?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图找到一个简单的方法来将一个 URI 映射到一个 Path 任何特定的文件系统。以下似乎工作,但需要一个可疑的技术:

  public void process(URI uri)throws IOException {
try {
//首先尝试通过现有文件系统获取路径。 (默认fs)
路径路径= Paths.get(uri);
doSomething(uri,path);

catch(FileSystemNotFoundException e){
//没有现有的文件系统,所以请尝试创建一个。 (罐子,拉链等)
地图< String,?> env = Collections.emptyMap();
try(FileSystem fs = FileSystems.newFileSystem(uri,env)){
Path path = fs.provider()。getPath(uri); // yuck :(
//断言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);
}

在一些示例上运行这段代码会产生如下结果:

$ $ $ $ $ $ $ c $ 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

请注意, URI 已被映射到已被植入的 Path 转换成正确的 FileSystem 类型,就像指向jar里面的/ org / foo目录的路径



什么这个代码困扰我,虽然NIO2可以很容易地:


  • 将URI映射到现有的 >文件系统: Paths.get(URI)

  • 将URI映射到 new FileSystem instance: FileSystems.newFileSystem(uri,env)



...将URI映射到 new FileSystem 实例中的路径没有好的方法。 p>

我能找到的最好的方法就是在创建一个FileSystem之后,我可以让它的 FileSystemProvider 给我Path: p>

  Path path = fs.provider()。getPath(uri); 

但是这似乎是错误的,因为不能保证它会返回绑定到FileSystem的Path我刚刚实例化(即, path.getFileSystem()== fs )。它非常依赖于FileSystemProvider的内部状态来知道我指的是哪个FileSystem实例。有没有更好的方法?

解决方案

Q:我试图找到一个简单的方法来映射一个URI到路径而不写特定于任何特定文件系统的代码

没有这样的方式



整个问题只有在与URI相关的文件系统尚未打开时才有意思,例如,当getFileSystem(在Paths.get中)抛出FileSystemNotFoundException时。
但要调用newFileSystem,您需要知道两件事:

$ ul

  • 用来创建新的URI的一部分文件系统。文件说,即在默认文件系统的情况下,URI的路径组件必须是根。例如getFileSystem(URI.create(file:/// duda,Collections.EMPTY_MAP)失败。
  • 在环境映射中设置什么,例如可能是密码。



  • 所以要从一个URI创建一个新的文件系统,你必须有关于要创建的文件系统的知识。


    I'm trying to find an easy way to map a URI to a Path without writing code specific to any particular file system. The following seems to work but requires a questionable technique:

    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);
    }
    

    Running this code on a couple examples produces the following:

    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
    

    Notice how the URIs have been mapped to Path objects that have been "rooted" into the right kind of FileSystem, like the Path referring to the directory "/org/foo" inside a jar.

    What bothers me about this code is that although NIO2 makes it easy to:

    • map a URI to a Path in existing file systems: Paths.get(URI)
    • map a URI to a new FileSystem instance: FileSystems.newFileSystem(uri, env)

    ... there is no nice way to map a URI to a Path in a new FileSystem instance.

    The best I could find was, after creating a FileSystem, I can ask its FileSystemProvider to give me Path:

    Path path = fs.provider().getPath(uri);
    

    But this seems wrong as there is no guarantee it will return a Path that is bound to the FileSystem that I just instantiated (i.e., path.getFileSystem() == fs). It's pretty much relying on the internal state of FileSystemProvider to know what FileSystem instance I'm referring to. Is there no better way?

    解决方案

    Q: "I'm trying to find an easy way to map a URI to a Path without writing code specific to any particular file system"

    A: There is no such way

    The whole question is only interesting if the filesystem associated with the URI is not open yet, i.e. when getFileSystem (in Paths.get) throws FileSystemNotFoundException. But to call newFileSystem you need to know 2 things:

    • what (part of the) URI to use to create the new filesystem. The docu says that i.e. in the case of the default filesystem the path component of the URI must be a root. e.g. getFileSystem( URI.create( "file:///duda", Collections.EMPTY_MAP) fails.
    • what to set in the environment map, e.g. might be a password.

    So to create a new filesystem from an URI you must have knowledge about the filesystem to create.

    这篇关于NIO2:如何一般地将URI映射到路径?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆