简单的Java程序:
public static String loadText(String file) {
StringBuilder finalString = new StringBuilder();
InputStream in = null;
BufferedReader reader = null;
InputStreamReader isr = null;
try{
System.out.println("Text File: " + file);
// Version 1
//URL url = Thread.currentThread().getClass().getResource(file);
//in = url.openStream();
// Version 2
in = Class.class.getResourceAsStream(file);
isr = new InputStreamReader(in);
reader = new BufferedReader(isr);
String line;
while((line = reader.readLine()) != null) {
finalString.append(line).append("//\n");
}
}
catch(IOException e) {
e.printStackTrace();
System.exit(-1);
}
finally {
try {
if (isr != null) { isr.close(); }
if (reader != null) { reader.close(); }
if (in != null) { in.close(); }
} catch (IOException e) { e.printStackTrace(); }
}
return finalString.toString();
}
getResource
和getResourceAsStream
方法在JDK 8(java-8-openjdk-amd64)中可以正常工作,但它们始终在JDK 11中返回null
。
问题:为什么?我该如何解决?
答案 0 :(得分:4)
我已经在MacOS上同时使用openjdk 8和11尝试了您的应用程序,但不能同时使用它们。我认为您需要查看[1]和[2]才能了解getResourceAsStream
的工作方式。
TLDR:
如果路径是绝对路径(即以斜杠-/
开头),则class.getResourceAsStream()
将在提供的路径中搜索
如果路径不是绝对路径(即,不是以斜杠开头),则class.getResourceAsStream()
将在与包名称相对应的构造路径中进行搜索,在该路径中,点用斜杠替换
所以它是否起作用取决于两件事:
file
是否与该类位于同一包中? 基本上在提供的示例中,如果路径不是绝对路径,它将永远无法工作,因为Class.class.getResourceAsStream()
将始终将路径解析为java/lang/<file>
,因此您的文件必须位于系统软件包中。因此,您必须使用<MyClass>.class.getResourceAsStream()
或使用绝对路径
[1] https://docs.oracle.com/javase/7/docs/api/java/lang/ClassLoader.html#getResource(java.lang.String)
[2] https://docs.oracle.com/javase/7/docs/api/java/lang/Class.html#getResource%28java.lang.String%29
由于Java SE 9在命名模块中的类上调用getResourceXXX只会在该模块中定位资源,因此不会像在先前版本中那样搜索类路径。因此,当您使用Class.class.getResourceAsStream()
时,它将尝试在包含java.lang.Class
的模块(即java.base
模块)中查找资源。显然,您的资源不在该模块中,因此它返回null。
您必须使Java 9+在模块中搜索文件,该文件很可能是“未命名的模块”。您可以通过将Class
更改为模块中定义的任何类来实现,以使Java使用正确的类加载器。
答案 1 :(得分:1)
还有一种使用ClassLoader
ClassLoader.getSystemResourceAsStream(file)
从所有位置加载。我正在使用它从仅包含资源且没有可执行代码的JAR文件中加载资源,因此上一个技巧无法使用,因为JAR中没有SomeClass
做SomeClass.class.getResourceAsStream()
我只是不了解内部原理,还必须更改文件的路径。
我在JAR归档文件的根目录中有一个JAR文件,文件名为“ my-file.txt”。
对于Java 8,此方法有效
Class.class.getResourceAsStream("/my-file.txt");
对于Java 11,即使文件位于根路径中,我也必须删除前导/
ClassLoader.getSystemResourceAsStream("my-file.txt");