IT-Swarm.Net

getResourceAsStream返回null

我正在我的Java项目的已编译JAR中的包中加载一个文本文件。相关目录结构如下:

/src/initialization/Lifepaths.txt

用于加载文件的代码是:

public class Lifepaths {
    public static void execute() {
        System.out.println(Lifepaths.class.getClass().
            getResourceAsStream("/initialization/Lifepaths.txt"));
    }

    private Lifepaths() {}

    //This is temporary; will eventually be called from outside
    public static void main(String[] args) {execute();}
}

无论我使用什么,打印输出都将始终打印null。我不确定为什么以上都行不通,所以我也尝试过:

  • "/src/initialization/Lifepaths.txt"
  • "initialization/Lifepaths.txt"
  • "Lifepaths.txt"

这些都不奏效。 众多问题 到目前为止关于这个主题,但没有一个有用 - 通常,他们只是说使用根路径加载文件,我已经在做了。那,或者只是从当前目录加载文件(只是加载filename),我也尝试过。该文件正在具有适当名称的适当位置编译到JAR中。

我该如何解决这个问题?

142
Aza

Lifepaths.class.getClass().getResourceAsStream(...)使用系统类加载器加载资源,它显然失败,因为它没有看到你的JAR

Lifepaths.class.getResourceAsStream(...)使用加载Lifepaths类的相同类加载器加载资源,它应该可以访问JAR中的资源

133
hoaz

规则如下:

  1. 检查要在JAR中加载的文件的位置(从而确保它实际添加到JAR中)
  2. 使用绝对路径:路径从JAR的根开始
  3. 使用相对路径:path从你正在调用的类的包目录开始getResource/getResoucreAsStream

并尝试:

Lifepaths.class.getResourceAsStream("/initialization/Lifepaths.txt")

代替

Lifepaths.class.getClass().getResourceAsStream("/initialization/Lifepaths.txt")

(不确定它是否有所作为,但前者将使用正确的ClassLoader/JAR,而我不确定后者)

52
Puce

因此,有几种方法可以从jar获取资源,每种方法的语法略有不同,其中路径需要以不同方式指定。

我见过的最好的解释是来自 JavaWorld 的这篇文章。我将在这里总结,但如果你想了解更多,你应该查看这篇文章。

方法

1)ClassLoader.getResourceAsStream()

格式:“/” - 分隔名称;没有前导“/”(所有名称都是绝对的)。

示例:this.getClass().getClassLoader().getResourceAsStream("some/pkg/resource.properties");

2)Class.getResourceAsStream()

格式:“/” - 分隔名称;前导“/”表示绝对名称;所有其他名称都相对于类的包

示例:this.getClass().getResourceAsStream("/some/pkg/resource.properties");

42
greedybuddha

不要使用绝对路径,使它们相对于项目中的“resources”目录。快速而脏的代码,显示目录“resources”中MyTest.txt的内容。

@Test
public void testDefaultResource() {
    // can we see default resources
    BufferedInputStream result = (BufferedInputStream) 
         Config.class.getClassLoader().getResourceAsStream("MyTest.txt");
    byte [] b = new byte[256];
    int val = 0;
    String txt = null;
    do {
        try {
            val = result.read(b);
            if (val > 0) {
                txt += new String(b, 0, val);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } 
    } while (val > -1);
    System.out.println(txt);
}
12
Paul Smith

您可能想尝试这个来获取流,即首先获取URL,然后将其作为流打开。

URL url = getClass().getResource("/initialization/Lifepaths.txt"); 
InputStream strm = url.openStream(); 

我曾经有一个类似的问题: 从jar读取txt文件失败但读取图像有效

9
MrD

您正在使用的ClassLoader似乎存在问题。使用contextClassLoader加载类。这与它是否采用静态/非静态方法无关

Thread.currentThread().getContextClassLoader().getResourceAsStream......

7
Binita Bharati

不知道是否有帮助,但在我的情况下,我的资源在/ src /文件夹中,并且收到此错误。然后我将图片移动到bin文件夹,它修复了问题。

2
Leo Ufimtsev

确保您的资源目录(例如“src”)在您的类路径中(确保它是Eclipse中构建路径中的源目录)。

确保从主类加载器加载clazz。

然后,要加载src/initialization/Lifepaths.txt,请使用

clazz.getResourceAsStream("/initialization/Lifepaths.txt");

为什么:clazz.getResourcesAsStream(foo) 在clazz的类路径中查找foo 相对于clazz所在的目录 。前导“/”使其从clazz的类路径中的任何目录的根加载。

除非你是某种类型的容器,比如Tomcat,或者直接使用ClassLoaders,否则你可以将Eclipse /命令行类路径视为唯一的类加载器类路径。

2
Bobby Martin

我发现自己处于类似的问题。由于我正在使用maven,我需要更新我的pom.xml以包含以下内容:

   ...
</dependencies>
<build>
    <resources>
        <resource>
            <directory>/src/main/resources</directory>
        </resource>
        <resource>
            <directory>../src/main/resources</directory>
        </resource>
    </resources>
    <pluginManagement>
        ...

请注意其中的资源标记以指定该文件夹的位置。如果您有嵌套项目(就像我一样),那么您可能希望从其他区域获取资源,而不仅仅是在您正在使用的模块中。如果您使用类似的配置数据,这有助于减少在每个仓库中保留相同的文件

1
plosco

在我的情况下没有任何工作,除非我从文件名中删除空格...

0
user3563159

对我有用的是在My Project/Java Resources/src下添加该文件,然后使用

this.getClass().getClassLoader().getResourceAsStream(myfile.txt);

我不需要明确地将此文件添加到路径中(显然将它添加到/ src)

0
CRDev