在创建资源路径时从ZipFileSystemProvider获取FileSystemNotFoundException

我有一个Maven项目,在一个方法中我想为我的资源文件夹中的目录创建一个路径。 这样做是这样的:

try { final URI uri = getClass().getResource("/my-folder").toURI(); Path myFolderPath = Paths.get(uri); } catch (final URISyntaxException e) { ... } 

生成的URI看起来像jar:file:/C:/path/to/my/project.jar!/my-folder

堆栈跟踪如下:

 Exception in thread "pool-4-thread-1" java.nio.file.FileSystemNotFoundException at com.sun.nio.zipfs.ZipFileSystemProvider.getFileSystem(ZipFileSystemProvider.java:171) at com.sun.nio.zipfs.ZipFileSystemProvider.getPath(ZipFileSystemProvider.java:157) at java.nio.file.Paths.get(Paths.java:143) 

URI似乎有效。 之前的部分! 指向生成的jar文件及其后面的部分到归档根目录中的my-folder 。 我之前使用过这些说明来创建资源的路径。 为什么我现在得到例外?

您需要先创建文件系统,然后才能访问zip中的路径

 final URI uri = getClass().getResource("/my-folder").toURI(); Map env = new HashMap<>(); env.put("create", "true"); FileSystem zipfs = FileSystems.newFileSystem(uri, env); Path myFolderPath = Paths.get(uri); 

这不是自动完成的。

见http://docs.oracle.com/javase/7/docs/technotes/guides/io/fsp/zipfilesystemprovider.html

如果您打算读取资源文件,可以直接使用getClass.getResourceAsStream 。 这将隐含地设置文件系统。 如果找不到您的资源,该函数将返回null ,否则您将直接拥有一个输入流来解析您的资源。

扩展@Uwe Allner的优秀答案,使用的故障安全方法是

 private FileSystem initFileSystem(URI uri) throws IOException { try { return FileSystems.getFileSystem(uri); } catch( FileSystemNotFoundException e ) { Map env = new HashMap<>(); env.put("create", "true"); return FileSystems.newFileSystem(uri, env); } } 

使用您要加载的URI调用此方法将确保文件系统处于工作状态。 使用后我总是调用FileSystem.close()

 FileSystem zipfs = initFileSystem(fileURI); filePath = Paths.get(fileURI); // Do whatever you need and then close the filesystem zipfs.close(); 

除了@Uwe Allner和@mvreijn之外:

小心URI 。 有时URI的格式错误(例如"file:/path/..." ,正确的是"file:///path/..." )并且您无法获得正确的文件系统。
在这种情况下,有助于从PathtoUri()方法创建URI

在我的例子中,我稍微修改了initFileSystem方法,并在非特殊情况下使用了FileSystems.newFileSystem(uri, Collections.emptyMap()) 。 在特殊情况下,使用FileSystems.getDefault()

在我的情况下,还需要捕获IllegalArgumentException来处理Path component should be '/' 。 在Windows和Linux上捕获exception,但FileSystems.getDefault()工作。 在osx上没有exception发生并且创建了newFileSystem

 private FileSystem initFileSystem(URI uri) throws IOException { try { return FileSystems.newFileSystem(uri, Collections.emptyMap()); }catch(IllegalArgumentException e) { return FileSystems.getDefault(); } }