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

时间:2014-07-30 09:02:43

标签: java maven

我有一个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。我之前使用过这些说明来创建资源的路径。为什么我现在得到例外?

4 个答案:

答案 0 :(得分:47)

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

这不是自动完成的。

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

答案 1 :(得分:8)

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

答案 2 :(得分: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);
    }
}

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

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

答案 3 :(得分:4)

除了@Uwe Allner和@mvreijn:

小心URI。有时,URI格式错误(例如"file:/path/...",而正确的格式为"file:///path/..."),您无法获得正确的FileSystem。 在这种情况下,从URI的{​​{1}}方法创建Path会有所帮助。

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

在我的情况下,还有必要抓住FileSystems.getDefault()来处理IllegalArgumentException的案例。在Windows和Linux上捕获异常,但Path component should be '/'有效。在osx上没有异常发生并且FileSystems.getDefault()被创建:

newFileSystem