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中的资源
规则如下:
- 检查你想要加载到JAR中的文件的位置(因此也要确保它实际上添加到了JAR中)
- 使用绝对path:path从JAR的根部开始
- 使用相对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你的代码将正确执行。