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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/25032716/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-10 23:28:36  来源:igfitidea点击:

Getting FileSystemNotFoundException from ZipFileSystemProvider when creating a path to a resource

javamaven

提问by stevecross

I have a Maven project and inside a method I want to create a path for a directory in my resources folder. This is done like this:

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

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

The generated URIlooks like jar:file:/C:/path/to/my/project.jar!/my-folder.

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

The stacktrace is as following:

堆栈跟踪如下:

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)

The URIseems to be valid. The part before !points to the generated jar-file and the part after it to my-folderin the root of the archive. I have used this instructions before to create paths to my resources. Why am I getting an exception now?

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

采纳答案by Uwe Allner

You need to create the file system before you can access the path within the zip like

您需要先创建文件系统,然后才能访问 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);

This is not done automatically.

这不是自动完成的。

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

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

回答by user5922822

If you intend to read the resource file, you can directly use getClass.getResourceAsStream. This will set up the file system implictly. The function returns nullif your resource could not be found, otherwise you directly have an input stream to parse your resource.

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

回答by mvreijn

Expanding on @Uwe Allner 's excellent answer, a failsafe method to use is

扩展@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);
    }
}

Calling this with the URI you are about to load will ensure the filesystem is in working condition. I always call FileSystem.close()after using it:

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

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

回答by schlegel11

In addition to @Uwe Allner and @mvreijn:

除了@Uwe Allner 和@mvreijn:

Be careful with the URI. Sometimes the URIhas a wrong format (e.g. "file:/path/..."and correct one would be "file:///path/...") and you cant get a proper FileSystem.
In this case it helps that the URIis created from the Path's toUri()method.

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

In my case I modified initFileSystemmethod a little bit and used in non exceptional cases the FileSystems.newFileSystem(uri, Collections.emptyMap()). In exceptional case the FileSystems.getDefault()is used.

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

In my case it was also necessary to catch the IllegalArgumentExceptionto handle the case with Path component should be '/'. On windows and linux the exception is caught but the FileSystems.getDefault()works. On osx no exception happens and the newFileSystemis created:

在我的情况下,还需要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();
    }
}