title: NIO2: how to generically map a URI to a Path?
body: <p>I'm trying to find an easy way to map a <code>URI</code> to a <code>Path</code> without writing code specific to any particular file system. The following seems to work but requires a questionable technique:</p>
  
  <pre><code>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&lt;String, ?&gt; 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);
  }
  </code></pre>
  
  <p>Running this code on a couple examples produces the following:</p>
  
  <pre><code>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
  </code></pre>
  
  <p>Notice how the <code>URI</code>s have been mapped to <code>Path</code> objects that have been "rooted" into the right kind of <code>FileSystem</code>, like the Path referring to the directory "/org/foo" inside a jar.</p>
  
  <p>What bothers me about this code is that although NIO2 makes it easy to:</p>
  
  <ul>
  <li>map a URI to a Path in <em>existing</em> file systems:  <code>Paths.get(URI)</code></li>
  <li>map a URI to a <em>new</em> <code>FileSystem</code> instance:  <code>FileSystems.newFileSystem(uri, env)</code></li>
  </ul>
  
  <p>... there is no nice way to map a URI to a Path in a <em>new</em> <code>FileSystem</code> instance.</p>
  
  <p>The best I could find was, after creating a FileSystem, I can ask its <code>FileSystemProvider</code> to give me Path:</p>
  
  <pre><code>Path path = fs.provider().getPath(uri);
  </code></pre>
  
  <p>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., <code>path.getFileSystem() == fs</code>). 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?</p>