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

ste*_*oss 33 java maven

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

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

生成的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)
Run Code Online (Sandbox Code Playgroud)

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

Uwe*_*ner 48

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

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

这不是自动完成的.

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


小智 10

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


sch*_*l11 10

除了@Uwe Allner 和@mvreijn:

小心URI. 有时候,URI有一个错误的格式(例如"file:/path/...",正确的人会"file:///path/..."),你不能得到正确的FileSystem
在这种情况下,URIPathtoUri()方法创建 是有帮助的。

就我而言,我initFileSystem稍微修改了方法并在非例外情​​况下使用了FileSystems.newFileSystem(uri, Collections.emptyMap()). 在特殊情况下FileSystems.getDefault()使用 。

在我的情况下,还需要IllegalArgumentException使用Path component should be '/'. 在 windows 和 linux 上,异常被捕获但FileSystems.getDefault()有效。在 osx 上没有异常发生并且newFileSystem创建了:

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


mvr*_*ijn 6

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

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

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

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

  • 注意,可以关闭“ ZipFileSystem”,但是会抱怨“ WindowsFileSystem”。 (2认同)