如何在另一个jar内的jar中创建一个FileSystem

Vic*_*azi 9 java nio

我正在尝试使用NIO FileSystem来访问另一个jar中的jar.调用外部jar my-outer.jar和内部my-inner.jar(使用Java 8和Windows 7,但我认为这不是问题)

我使用以下代码

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

但是我在尝试创建newFileSystem时遇到以下异常:

Exception in thread "main" java.nio.file.FileSystemNotFoundException: C:\testfs\my-outer.jar!\my-inner.jar
Run Code Online (Sandbox Code Playgroud)

请注意,如果我只使用外部jar作为FileSystem,它可以很好地工作,我可以很好地读取和写入文件.只是当我试图进入内部存档时,麻烦就开始了.

FileSystem不支持JarURLConnection表示法吗?

Ort*_*kni 2

正如 vbezhenear 所说和我自己的实验,表单中的 JarURLConnection 表示法c:/testfs/my-outer.jar!/my-inner.jar似乎不是由工厂方法实现的FileSystems.newFileSystem(Path path, ClassLoader loader)

但您仍然可以像这样访问内部罐子:

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)) {
       ...
    }
}
Run Code Online (Sandbox Code Playgroud)

- 更新 -

如果您尝试使用 anURI而不是 a,Path您可以创建ZipFileSystem这样的

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))
{...}
Run Code Online (Sandbox Code Playgroud)

但不幸的是你可以访问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
    }
}
Run Code Online (Sandbox Code Playgroud)

该路径在第一个路径之前被切断"!"。因此无法通过该newFileSystem方法直接在内部 jar 上创建文件系统。

  • “更新”只是为了表明您正在寻找的功能(尚未)尚未实现。(创建一个使用 JarURLConnection 表示法定位的 ZipFileSystem) (2认同)