我正在尝试使用NIO文件系统访问另一个罐子内的罐子。把外面的罐子叫做我的外在.jar把内在的罐子叫做我的内在.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))
{ ... }
但是在尝试创建该新文件系统时,我遇到了以下异常:
Exception in thread "main" java.nio.file.FileSystemNotFoundException: C:testfsmy-outer.jar!my-inner.jar
请注意,如果我只使用外部jar作为文件系统,则可以很好地工作,并且可以很好地从中读取和写入文件。只是当我试图进入内部档案时,麻烦就开始了。
文件系统不支持 JarURLConnection 表示法吗?
正如 vbezhenear 所说,正如我自己所实验的那样,c:/testfs/my-outer.jar!/my-inner.jar
形式的 JarURLConnection 表示法似乎没有通过工厂方法实现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)) {
...
}
}
--更新--
如果您尝试使用URI
而不是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))
{...}
但是运气不好,你可以进入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 上创建文件系统。
一个迟到的答案,但问题的标题是如何制作一个包含在另一个罐子中的 jar 的文件系统。 我对这个问题的解决方案是将包含的 jar 解压缩到临时位置,然后使用该提取的 jar 位置创建一个文件系统。如果您对提取的副本进行了任何更改,则必须将它们放回它来自的罐子中。当我不得不从 aar 文件中提取"类.jar"并将该罐子中的内容复制到另一个罐子时,我遇到了这个问题。就我而言,提取的副本永远不会被修改,因此简化了事情。