Java 如何从JAR中的类读取外部文件

Java 如何从JAR中的类读取外部文件,java,classloader,Java,Classloader,文件结构: /web-project | |---/WEB-INF/a.jar | |---/META-INF/resources/b.properties 位于A.jar中的A.class想要读取/META-INF/resources/b.properties 我认为a.jar和b.properties都在同一个类加载器下(因为它们在相同的web上下文中) 为了达到我的目的,我尝试了以下方法,但没有成功 InputStream is = null; ClassLoad

文件结构:

/web-project
   |
   |---/WEB-INF/a.jar
   |
   |---/META-INF/resources/b.properties
位于
A.jar
中的
A.class
想要读取
/META-INF/resources/b.properties

我认为a.jar和b.properties都在同一个类加载器下(因为它们在相同的web上下文中)

为了达到我的目的,我尝试了以下方法,但没有成功

InputStream is = null;
ClassLoader[] loaders = { Thread.currentThread().getContextClassLoader(),
    ClassLoader.getSystemClassLoader(), getClass().getClassLoader() };

ClassLoader currentLoader = null;
for (int i = 0; i < loaders.length; i++) {
    if (loaders[i] != null) {
        currentLoader = loaders[i];
        is = currentLoader.getResourceAsStream("/META-INF/resources/b.properties");
        if (is != null) { // is is always null no matter what ways I used.
            break;
        }
    }
}
似乎我应该使用
FileInputStream
来获取JAR之外的资源,而不是使用
getResourceAsStream()

====已更新2=====

最后,我用下面的解决方案解决了这个问题

context.getResourceAsStream("/META-INF/resources/b.properties");
基于以下前提条件:

a、 jar/b.properties在相同的上下文中


A.class
可以获得
ServletContext
对象

您可以通过首先验证jar文件的路径来解决此问题。您可以执行以下代码行并检查路径

 getClass().getProtectionDomain().getCodeSource().getLocation();
由于资源文件位于jar文件之外,因此需要更改jar文件的路径相对路径

Properties mainProperties = new Properties();
FileInputStream file = new FileInputStream("<relative-path>/META-INF/resources/b.properties");
mainProperties.load(file);
file.close();
似乎我应该使用
FileInputStream
来获取JAR之外的资源,而不是使用
getResourceAsStream()

根据定义,资源位于JAR文件中。它之外的任何内容都不是资源而是文件,您应该使用
FileInputStream
FileReader
来读取它。你可以用

URL url = getClass().getProtectionDomain().getCodeSource().getLocation();

要获取JAR文件的位置,如果您将该文件分发到同一目录中,您只需对其进行一点路径修改即可获得该文件的路径。

请发布一些我们可以运行的内容,或者至少了解一下您的程序的外观。此代码在哪个上下文中运行?Servlet初始化?请求处理?那么,您如何使用来自
jsp
Servlet
或任何其他类的类
A
?JAR文件中是否有资源?如果是这样的话,你发布的代码或任何简化版本都应该能找到它。如果没有,请不要。@Howard Wang您可以试试我发布的内容,如果行得通,请告诉我们。或者将代码更改为
A.class.getResourceAsStream(“/META-INF/resources/b.properties”)
,或者删除字符串参数中的初始斜杠(
/
)。Class.getResourceAsStream允许初始斜杠;ClassLoader.getResourceAsStream没有。getClass().getProtectionDomain().getCodeSource().getLocation()提供JAR文件的位置。这与JAR文件中资源的正确URI没有任何关系。@EJP看起来我用错了词。我指的是jar文件的位置。@EJP同时,OP请求访问jar文件之外的资源。如果您错过了问题的这一部分,
getResourceAsStream()
用于Jar文件内的资源,
META-INF
位于具有该路径的Jar文件内,前面没有任何内容,当然不是Jar文件自身的位置。这是不可能的。他自相矛盾。他声称它是外部的,但在这种情况下,为什么它会在META-INF中呢?注意:我很好奇你是如何测试一些不起作用的东西的。@EJP同意。就我而言,它不是META-INF文件夹。我根据他/她显示的文件夹结构创建了一个文件夹,然后进行了测试。
/web-project
   |
   |---/WEB-INF/a.jar
   |
   |---/test/resources/b.properties
URL url = getClass().getProtectionDomain().getCodeSource().getLocation();