【问题标题】:How to walk through Java class resources?如何遍历 Java 类资源?
【发布时间】:2009-04-14 22:02:27
【问题描述】:

我知道我们可以这样做:

Class.class.getResourceAsStream("/com/youcompany/yourapp/module/someresource.conf")

读取打包在我们的 jar 文件中的文件。

我用谷歌搜索了很多,我肯定没有使用正确的术语;我想做的是列出可用资源,如下所示:

Class.class.listResources("/com/yourcompany/yourapp")

这应该返回包内的资源列表com.yourcompany.yourapp.*

这可能吗?如果不能像我展示的那样轻松完成,有什么想法吗?

注意:我知道可以知道你的 jar 在哪里,然后打开它并检查它的内容以实现它。但是,在我现在工作的环境中,我做不到。

【问题讨论】:

  • 是否可以选择 ServiceLoader? stackoverflow.com/questions/251336 也就是说,您不是在运行时在类路径中列出“目录”,而是在编译时显式提供资源列表,并将其存储在类路径中一个众所周知的位置。

标签: java resources classpath


【解决方案1】:

对于 JAR 文件中的资源,类似这样的工作:

URL url = MyClass.class.getResource("MyClass.class");
String scheme = url.getProtocol();
if (!"jar".equals(scheme))
  throw new IllegalArgumentException("Unsupported scheme: " + scheme);
JarURLConnection con = (JarURLConnection) url.openConnection();
JarFile archive = con.getJarFile();
/* Search for the entries you care about. */
Enumeration<JarEntry> entries = archive.entries();
while (entries.hasMoreElements()) {
  JarEntry entry = entries.nextElement();
  if (entry.getName().startsWith("com/y/app/")) {
    ...
  }
}

您可以对文件系统或许多其他存储库中“爆炸”的资源执行相同的操作,但这并不那么容易。您需要为要支持的每个 URL 方案提供特定代码。

【讨论】:

  • 感谢这个例子,它是否使用类加载器来访问资源?或者它充当打开 jar 文件并手动检查其内容的助手?
  • 两者兼而有之。它使用类加载器来定位资源。然后你必须手动列出内容。我没有展示这个,但是一旦你有了内容列表,你可以根据需要返回到类加载器进行加载,或者直接从存档中加载它们。
  • 嗯,假设您在 appengine java vm 实现中。它不允许您打开文件。这或多或少是重点。所以我认为这是正确的答案,但我想做的事情是不可能的。不允许这样做可能会带来安全问题:(感谢埃里克森
  • 这些 jar 文件是您自己构建的吗?如果是这样,请添加一个包含其他文件列表的额外文件(具有固定名称)。
  • 注意,JarURLConnection.getJarFile 可能(并且通常应该)返回 null。按照 Jon Skeet 所说的做一些事情会更有意义。
【解决方案2】:

一般无法获得这样的资源列表。一些类加载器甚至可能能够支持这一点 - 想象一个可以从 Web 服务器获取单个文件的类加载器,但 Web 服务器不必支持列出目录的内容。 当然,对于 jar 文件,您可以显式加载 jar 文件的内容。

This question 类似,顺便说一句。)

【讨论】:

  • 很高兴了解为什么类加载器不允许它或为什么 jre 没有提供简单的方法来做到这一点:(
  • @David:我举了一个例子来说明为什么它并不总是可行 - 你在底层存储(网络)中的唯一访问权限是“获取此文件”。
  • 对不起,我明白了。这是我的英语不好,可能缺乏关注。现在我明白你了。谢谢
【解决方案3】:

我一直在寻找一种使用类加载器列出 jar 文件内容的方法,但不幸的是,这似乎是不可能的。相反,您可以做的是将 jar 作为 zip 文件打开并以这种方式获取内容。您可以使用标准 (here) 方式读取 jar 文件的内容,然后使用类加载器读取内容。

【讨论】:

    【解决方案4】:

    目前列出类路径中所有资源的最强大的机制是to use this pattern with ClassGraph,因为它处理widest possible array of classpath specification mechanisms,包括新的JPMS 模块系统。 (我是ClassGraph的作者。)

    List<String> resourceNames;
    try (ScanResult scanResult = new ClassGraph()
                .whitelistPaths("com/yourcompany/yourapp")
                .scan()) {
        resourceNames = scanResult.getAllResources().getNames();
    }
    

    【讨论】:

      【解决方案5】:

      我经常用

      getClass().getClassLoader().getResourceAsStream(...)
      

      但我怀疑您是否可以在不事先知道它们的情况下列出类路径中的条目。

      【讨论】:

      • 您能否出示一份参考资料,指出您所说的事实?
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-12-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-06-08
      相关资源
      最近更新 更多