2015-04-17 51 views
6

我想用NIO FileSystem訪問另一個jar裏面的jar。 調用外罐子我-outer.jar和內我-inner.jar (使用Java 8和Windows 7,但我認爲這不是問題)如何創建文件系統到另一個jar裏面的jar

我使用下面的代碼

String zipfilePath = "c:/testfs/my-outer.jar!/my-inner.jar"; 
    Path path = Paths.get(zipfilePath); 
    try(ZipFileSystem zipfs = (ZipFileSystem) FileSystems.newFileSystem(path, null)) 
    { ... } 

但試圖創建newFileSystem當我得到下面的異常:

Exception in thread "main" java.nio.file.FileSystemNotFoundException: C:\testfs\my-outer.jar!\my-inner.jar 

需要注意的是,如果我只使用外瓶的文件系統,完美的作品很好,我可以從它精美的讀取和寫入文件。只是當我試圖進入內部檔案庫時,麻煩就開始了。

不是FileSystem支持JarURLConnection表示法嗎?

+1

從查找到ZipFileSystem的反編譯源代碼,它似乎只支持「真實」文件。對於嵌套的ZIP(jar)壓縮包,你需要使用「低級別」java.util.zip包(或者將內部的arcive提取到磁盤上,儘管我不會說這是一個好的解決方案)。 – vbezhenar

+0

不是一個好主意。即使是一個級別的JAR文件系統也會表現很差。 – EJP

回答

3

正如vbezhenear所說的那樣,以及我自己的實驗,c:/testfs/my-outer.jar!/my-inner.jar形式的JarURLConnection符號似乎沒有通過工廠方法FileSystems.newFileSystem(Path path, ClassLoader loader)實施。

但你仍然可以訪問內瓶這樣的:如果您嘗試使用URI而不是Path,你可以創建一個ZipFileSystem這樣

Path outerPath = Paths.get("c:/testfs/my-outer.jar"); 
try (FileSystem outerFS = FileSystems.newFileSystem(outerPath, null)) { 
    Path innerPath = outerFS.getPath("/my-inner.jar"); 
    try (FileSystem innerFS = FileSystems.newFileSystem(innerPath, null)) { 
     ... 
    } 
} 

--UPDATE--

URI uri = URI.create("jar:file:/home/orto/stackoverflow/outer.jar!/inner.jar"); 
Map<String,String> env = Collections.emptyMap(); 
try(ZipFileSystem zipfs = (ZipFileSystem)FileSystems.newFileSystem(uri,env)) 
{...} 

,但沒有運氣你訪問outer.jar而不是inner.jar

如果你看看JarFileSystemProvider的源代碼,你看到

@Override 
protected Path uriToPath(URI uri) { 
    String scheme = uri.getScheme(); 
    if ((scheme == null) || !scheme.equalsIgnoreCase(getScheme())) { 
     throw new IllegalArgumentException("URI scheme is not '" + getScheme() + "'"); 
    } 
    try { 
     String uristr = uri.toString(); 
     int end = uristr.indexOf("!/"); 
     uristr = uristr.substring(4, (end == -1) ? uristr.length() : end); 
     uri = new URI(uristr); 
     return Paths.get(new URI("file", uri.getHost(), uri.getPath(), null)) 
        .toAbsolutePath(); 
    } catch (URISyntaxException e) { 
     throw new AssertionError(e); //never thrown 
    } 
} 

第一"!"之前的路徑被切斷了。因此,無法從newFileSystem方法的內部jar中直接創建文件系統。

+0

我喜歡你的第一個答案。我不明白你的「更新」是否給出了另一個答案或只是解釋我的問題 –

+2

「更新」僅僅是爲了表明你正在尋找的功能還沒有實現。 (創建一個使用JarURLConnection表示法的ZipFileSystem) –

+0

這個(不再像8u74那樣)作爲'FileSystems.newFileSystem(innerPath,null)''拋出'ProviderNotFoundException'因爲'ZipFileSystemProvider.newFileSystem() .getFileSystem()!= FileSystems.getDefault()'。 – antak