【问题标题】:Find filenames in a folder inside nested JARs在嵌套 JAR 内的文件夹中查找文件名
【发布时间】:2019-11-22 01:33:14
【问题描述】:

当我的应用程序打包为 JAR 时,我无法访问目标文件夹“images”。 我不是在获取单个文件后,我想要的是“图像”文件夹中所有 .jpg 文件的列表。

我试过这个: URI uri = getClass().getClassLoader.getResource("images").toURI();

这会返回:jar:file:/C:/test-1.0-SNAPSHOT.jar!/BOOT-INF/lib/core-1.0-SNAPSHOT.jar!/images

然后我尝试创建一个流来迭代这样的文件:

FileSystem fs = FileSystems.newFilesSystem(uri, Collections.emptyMap());
Path p = fs.getPath("images");
Files.walk(p).forEach(path -> System.out.println(path));

这只会给 med 一个 FileNotFoundException。

那么,如何访问嵌套 JAR 中的“images”文件夹?

编辑:这不是重复的:How to list the files inside a JAR file?。我已经尝试了那里的所有东西。不同之处在于我在另一个 JAR 内有一个 JAR,嵌套 JAR。我认为这就是造成问题的原因。

【问题讨论】:

  • 我写了一个答案,但没有及时发布。你可以在这里看到它:pastebin.com/bViDmy53
  • @lino-says-reinstate-monica 可以请您删除重复的标签,因为这是错误的吗?

标签: java java-8


【解决方案1】:

在 JDK 12 之前,内置 ZipFileSystem 中根本不支持嵌套 jar 文件。

例如,ZipFileSystemProvider 接受 PathnewFileSystem 方法有如下语句

if (path.getFileSystem() != FileSystems.getDefault()) {
    throw new UnsupportedOperationException();
}

即使对于 JDK 12,由于对 jar: URL 的一贯滥用,掌握嵌套的 zip 文件系统也并非易事。

jar: URL has been specified 的语法为:

jar:<url>!/{entry}

这意味着您的资源的正确 URL 应该是

outer file                file:/C:/test-1.0-SNAPSHOT.jar
nested jar file       jar:file:/C:/test-1.0-SNAPSHOT.jar!/BOOT-INF/lib/core-1.0-SNAPSHOT.jar
entry of nested   jar:jar:file:/C:/test-1.0-SNAPSHOT.jar!/BOOT-INF/lib/core-1.0-SNAPSHOT.jar!/images

要解析这样的 URL,您必须使用第一个 jar: 和最后一个 !/ 之间的部分提取 jar 文件的位置并递归解析它。 但是,我见过的所有 JDK 代码,无论支持 URL API 还是 FileSystem API 始终未能这样做,使用 indexOf("!/") 而不是 lastIndexOf("!/")。 所以嵌套的jar: URIs/URLs 根本不起作用。

获得嵌套文件系统的唯一方法是使用已与FileSystem 关联的Path 实例打开它们:

Path outer = Paths.get("C:", "test-1.0-SNAPSHOT.jar");
ClassLoader cl = null;
try(FileSystem outerFs = FileSystems.newFileSystem(outer, cl);
    FileSystem innerFs = FileSystems.newFileSystem(
        outerFs.getPath("/BOOT-INF/lib/core-1.0-SNAPSHOT.jar"), cl) ) {

    Path p = innerFs.getPath("images");
    Files.walk(p).forEach(path -> System.out.println(path));
}

这适用于 JDK12 或更高版本。

【讨论】:

  • 谢谢,是的,我已经在 J​​DK 8 上尝试了你的最后一个建议,只是在那里抛出了一个 ProviderNotFoundException:(。通过在 txt 文件中列出我需要的文件的名称来解决这个问题. 它不漂亮,但它的工作原理
  • 嗯,是的,FileSystems.newFileSystem 将遍历已安装的提供程序,探测它们并捕获UnsupportedOperationException,继续迭代,最终说没有找到匹配的提供程序。您可以手动迭代提供程序,找到正确的提供程序并请求它创建一个新的文件系统;这就是我发现它抛出UnsupportedOperationException...
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-03-31
  • 2011-07-27
  • 1970-01-01
  • 1970-01-01
  • 2023-04-02
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多