我正在从我的Java项目的编译JAR中的包中加载一个文本文件。相关目录结构如下:
/src/initialization/Lifepaths.txt
我的代码通过调用Class::getResourceAsStream来返回一个InputStream来加载一个文件。
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 / / Lifepaths.txt”
“初始化/ Lifepaths.txt”
“Lifepaths.txt”
这两种方法都不起作用。到目前为止,我已经阅读了许多关于这个主题的问题,但没有一个是有帮助的——通常,他们只是说使用根路径加载文件,而我已经这样做了。或者只是从当前目录加载文件(只是加载文件名),我也尝试过。该文件将被编译到JAR中的适当位置,并具有适当的名称。
我怎么解决这个问题?
默认的JVM类加载器将首先使用父类加载器加载资源:
.
lifepathways .class. getclass()的类加载器是引导类加载器,所以getResourceAsStream只搜索$JAVA_HOME,而不管用户提供的类路径是什么。显然,Lifepaths.txt不在那里。
Lifepaths.class的类加载器是系统类路径类加载器,所以getResourceAsStream将搜索用户定义的类路径,Lifepaths.txt在那里。
当使用java.lang.Class#getResourceAsStream(字符串名称)时,不以'/'开头的名称将作为包名的前缀添加。要避免这种情况,请使用java.lang。类加载器# getResourceAsStream代替。
例如:
ClassLoader loader = Thread.currentThread().getContextClassLoader();
String resourceName = "Lifepaths.txt";
InputStream resourceStream = loader.getResourceAsStream(resourceName);
因此,从jar中获取资源有几种方法,每种方法的语法略有不同,需要指定不同的路径。
我所看到的最好的解释是来自InfoWorld的这篇文章。我在这里总结一下,但如果你想了解更多,你应该看看这篇文章。
方法
ClassLoader.getResourceAsStream()。
格式:“/”-以名称分隔;没有前导“/”(所有名称都是绝对的)。
例如:this.getClass () .getClassLoader () .getResourceAsStream(“一些/ pkg / resource.properties”);
Class.getResourceAsStream ()
格式:“/”-以名称分隔;前导“/”表示绝对名称;所有其他名称都是相对于类的包
例如:this.getClass () .getResourceAsStream(" /一些/ pkg / resource.properties”);
2020年9月更新:更改文章链接。原文来自Javaworld,它现在托管在InfoWorld上(并且有更多广告)