簡體   English   中英

在創建資源路徑時從ZipFileSystemProvider獲取FileSystemNotFoundException

[英]Getting FileSystemNotFoundException from ZipFileSystemProvider when creating a path to a resource

我有一個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<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

如果您打算讀取資源文件,可以直接使用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);
    }
}

使用您要加載的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/..." ),你不能得到適當的FileSystem
在這種情況下,它有助於從PathtoUri()方法創建URI

在我的例子中,我稍微修改了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();
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM