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

Java 创建资源路径时从ZipFileSystemProvider获取FileSystemNotFoundException,java,maven,Java,Maven,我有一个Maven项目,在一个方法中,我想为我的resources文件夹中的目录创建一个路径。这是这样做的: 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

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

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/我的文件夹

stacktrace如下所示:

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<String, String> env = new HashMap<>(); 
env.put("create", "true");
FileSystem zipfs = FileSystems.newFileSystem(uri, env);
Path myFolderPath = Paths.get(uri);
final URI=getClass().getResource(“/myfolder”).toURI();
Map env=new HashMap();
环境出售(“创建”、“真实”);
FileSystem zipfs=FileSystems.newFileSystem(uri,env);
Path myFolderPath=Path.get(uri);
这不是自动完成的


请参见

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

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

除了@Uwe Allner和@mvreijn:

小心使用
URI
。有时
URI
的格式错误(例如
文件:/path/…“
正确的格式是
”file:///path/...“
)并且您无法获得适当的
文件系统

在这种情况下,从
路径
toUri()方法创建
URI
会有所帮助。 在我的例子中,我稍微修改了
initFileSystem
方法,并在非异常情况下使用了
FileSystems.newFileSystem(uri,Collections.emptyMap())
。在例外情况下,将使用
FileSystems.getDefault()
。 在我的例子中,还需要捕获
IllegalArgumentException
来处理
路径组件应为“/”
的情况。在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();
    }
}

Zip文件的格式是否可由ZipFileSystemProvider读取?该文件夹存在于根目录中。jar文件是由Maven生成的,因此它应该是可读的。如果您已经拥有
URL
,您不需要
文件或
路径来读取它的内容。您只需调用
URL.openStream()
并读取该方法返回的
InputStream
。如果您实际上必须有一个
文件
路径
对象,那么您将需要下面提到的
文件系统
修复。但大多数东西实际上并不需要文件,可以处理
InputStream
Reader
接口,因此我建议尽可能先使用
URL.openStream()
路径。小心,可以关闭
ZipFileSystem
,但是一个
WindowsFileSystem
会抱怨。我使用同样的技术来访问jar文件。但我面临的问题是,每当路径中有空格字符时,我都会得到相同的错误。它也可以正常工作是的,文件路径中超出ASCII范围的空格和字符会导致nio出现问题。当jar/zip中的文件包含这些字符时,也是如此。但这是另一个问题,您可以在此处找到帮助:
private FileSystem initFileSystem(URI uri) throws IOException {
    try {
        return FileSystems.newFileSystem(uri, Collections.emptyMap());
    }catch(IllegalArgumentException e) {
        return FileSystems.getDefault();
    }
}