文件和bundle资源URLs

9

我已经为这个问题苦恼了相当长一段时间,但找不到解决方案:

我有一个使用自定义库打包成jar的Eclipse RCP应用程序。从插件中,我调用jar中的一个方法。 在这个方法中,我使用this.class.getResource(relPath)获取资源,其中relPath是我需要的文件的硬编码相对路径。这会返回一个可以用来构造FileURL

现在,如果我不是从插件而是从简单的Java程序中调用此方法,它就完美地工作。 区别在于:Eclipse RCP的类加载器返回协议为bundleresource://URL,而这种协议不受File支持;而在运行简单的Java程序时,返回的是file:// URL,这完全可以用来构造File

我知道Eclipse SDK的FileLocator类(将bundleresource-URL解析为file-URL),但我不能在库中使用它,因为我不想将其与Eclipse RCP平台绑定-也应该可以从非Eclipse RCP源使用此库。

有没有人有任何想法,如何以一种方式从相对路径加载此资源,使得无论从Eclipse RCP-插件还是任何其他客户端调用该方法都可以工作?

我需要在这个相对路径的目录上构造一个File以搜索其中的文件。我完全陷入困境...

更新:如果有可能使用除File#list()之外的其他方法来获取目录内容,这已经可以帮助我了。

非常感谢任何提示,


@TonnyMadsen 嗯,我可以这样做,但基本上很简单:我正在使用this.getClass().getResource(relPath)来加载我的classPath中的路径。在Eclipse RCP下完成后,这会返回一个bundleresource:// URL,否则将返回一个file:// URL。 尝试创建File-Object会因为File不支持此协议而失败bundleresource:// URL。 由于我需要读取“relPath”的目录内容,所以我被迫使用File... - quaylar
你如何将URL转换为文件? - Tonny Madsen
在这种情况下,它只适用于file://类型的URL... 有可插拔的API可以将URL转换为流,但不能转换为文件。同样在这里指出:https://dev59.com/HXE85IYBdhLWcg3wUBoZ - Tonny Madsen
@TonnyMadsen 是的,我知道,这正是我的问题 :) 这就是为什么我对其他人如何处理这个问题感兴趣,我猜有些人已经遇到了这个问题(使用 Eclipse 类加载器加载资源并需要文件引用)。 - quaylar
@TonnyMadsen:是的,但我的意思是:我需要将FileLocator类(以及它的所有依赖项)与我的库捆绑在一起,以便在没有Eclipse参与的情况下仍然可以正常工作(例如,在Web-应用程序中使用)。 - quaylar
显示剩余6条评论
2个回答

14

您是否可以简单地反转依赖关系。即,您的模块作为URL检索资源定义了一个接口

interface Locator { URL resolve(URL url); }

你可以使用默认实现。

class StandaloneLocator implements Locator {
   public URL resolve(URL url) { return url; }
}

在Eclipse中,这个默认的定位器需要被替换为

class EclipseLocator implements Locator {
  public URL resolve(URL url) { return FileLocator.resolve(url); }
}

现在,你的库不依赖于Eclipse,仍然可以使用FileLocator。由于没有Eclipse,您将不会获得任何bundleresource-URL,这应该可以工作。

Cheers, Jens


在你回答之前,我已经绕过了这个问题本身,但这确实是一个非常好的想法!感谢您,下次可能会进行重构 :) - quaylar

0

使用Class的方法无法枚举jar文件中的文件。您需要创建一个包含所有资源名称的resourcelist文件,或者像打开zip存档文件一样打开jar文件并枚举文件。 File类无法处理除file://之外的协议。如果您的资源在jar文件中,则应使用Url类,并使用Url.openSteram方法获取文件内容的流。

更新关于运行简单Java应用程序:您可能没有将其打包到jar文件中,因此您的类和资源放置在文件系统中而不是存档中。这就是为什么您会得到file://协议的原因。如果您打包到jar文件中,则协议将不是file://,而是jar://(确切的协议名称不确定)。


感谢您的答复,但该文件/资源不在一个jar文件中,而是在应用程序类路径内的一个目录中。 关于Url.openStream():很遗憾,使用此方法无法读取目录内容(我需要将目录加载为资源并检查现有文件)。 - quaylar

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接