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"

这些都不起作用。 到目前为止, 我已经 阅读 了许多关于这个主题的问题,但是没有一个是有帮助的 – 通常他们只是说使用根path加载文件,我已经在做这个。 这个,或者只是从当前目录加载filename (只是加载filename ),我也试过了。 正在使用适当的名称将文件编译到适当位置的JAR中。

我如何解决这个问题?

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

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

规则如下:

  1. 检查你想要加载到JAR中的文件的位置(因此也要确保它实际上添加到了JAR中)
  2. 使用绝对path:path从JAR的根部开始
  3. 使用相对path:path从你调用的类的包目录开始getResource / getResoucreAsStream

并尝试:

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

代替

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

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

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

我看到的最好的解释是来自JavaWorld的这篇文章。 我会在这里总结,但如果你想知道更多,你应该看看这篇文章。

方法

1) ClassLoader.getResourceAsStream()

格式:“/” – 分隔的名字; 没有领先的“/”(所有的名字都是绝对的)。

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

2) Class.getResourceAsStream()

格式:“/” – 分隔的名字; 前导“/”表示绝对名称; 所有其他的名字都是和这个类的包相关的

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

不要使用绝对path,使它们相对于项目中的“资源”目录。 快速和肮脏的代码,显示目录“资源”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); } 

你可能想要尝试这个获取stream,即首先得到的url,然后打开它作为stream。

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

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

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

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

不知道是否有帮助,但在我的情况下,我有我的资源在/ src /文件夹,并得到这个错误。 然后,我将图片移动到bin文件夹,并解决了问题。

确保你的资源目录(例如“src”)在你的类path中(确保它是eclipse中构buildpath的源代码目录)。

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

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

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

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

除非你在像Tomcat这样的容器中,或者直接使用ClassLoader来做什么,那么你可以把你的eclipse /命令行类path作为唯一的类加载器类path。

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

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

我不需要明确地将这个文件添加到path(添加到/ src显然)

我发现自己也有类似的问题。 由于我使用maven我需要更新我的pom.xml包含这样的东西:

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

注意那里的资源标签来指定文件夹的位置。 如果你有嵌套的项目(就像我这样做),那么你可能想从其他领域获取资源,而不是在你正在工作的模块中。这有助于减less在每个回购中保留相同的文件,如果你使用类似的configuration数据

您的文件被放入错误的文件夹。 JVM将尝试find您的软件包并查找bin,但是您的文件不在JVMsearch区域。 我发现这个video是非常有用的,你会解决它,找出你应该把你的文件放在哪里: https : //www.youtube.com/watch?v=0VzStS1b504

@Emracool …我build议你select一个。 由于您似乎正在尝试加载* .txt文件。 最好使用FileInputStream()而不是getClass().getClassLoader().getResourceAsStream()getClass().getResourceAsStream() 。 至less你的代码将正确执行。