我创建了一个Gradle项目,该项目使用类加载器从子目录资源/文本加载文本文件。此时它可以工作,但是当我将项目转换为模块化JavaFX程序时,相同的类加载器函数将提供NullPointerException。
└───src
└───main
├───java
│ │ module-info.java
│ └───app
│ Main.java
└───resources
└───text
words.txt
plugins {
id 'application'
id 'org.openjfx.javafxplugin' version '0.0.8'
}
sourceCompatibility = 11
repositories {
jcenter()
}
javafx {
version = '13.0.1'
modules = [ 'javafx.controls']
}
mainClassName = 'exMod/app.Main'
jar {
manifest {
attributes 'Main-Class': mainClassName
}
}
module exMod {
requires javafx.controls;
exports app;
}
package app;
import javafx.application.Application;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
public class Main extends Application {
public static void main(String[] args){ launch(); }
public void start(Stage stage){
stage.setTitle("Hello World!");
Button button = new Button();
Label label = new Label();
button.setText("Click me!");
button.setOnAction(event -> label.setText(getWords()));
VBox root = new VBox();
root.setAlignment(Pos.CENTER);
root.getChildren().addAll(button, label);
stage.setScene(new Scene(root, 300, 250));
stage.show();
}
private String getWords(){
String path = "text/words.txt";
InputStream inputStream = getClass().getClassLoader().getResourceAsStream(path);
InputStreamReader isReader = new InputStreamReader(inputStream); // null exception
BufferedReader reader = new BufferedReader(isReader);
StringBuilder content = new StringBuilder();
try {
String line;
while( (line = reader.readLine()) != null) {
content.append(line);
}
} catch(IOException e){
e.printStackTrace();
}
return content.toString();
}
}
如果我将路径变量更改为“ words.txt”,并将文本文件上移至src / main / resources,则可以正常工作,但是由于某种原因,我一直无法发现,因此无法从资源子目录将不起作用。是什么引起了NullPointerException,我该如何解决?
[在this question的注释中,用户Holger声明为program.class.getClassLoader().getResource("b/text.txt")
的替代项
...您应该使用
program.class.getResource("b/text.txt")
相对于程序类的位置解析资源。否则,一旦使用模块,它在Java 9或更高版本中可能会失败。进入类加载器将破坏有关实际模块。
因此,我尝试仅使用getClass().getResourceAsStream(path)
而不是getClass().getClassLoader().getResourceAsStream(path)
。
[我也阅读了艾伦·贝特曼(Alan Bateman)对this question的评论,]
资源已封装,因此无法在ClassLoader中找到蜜蜂。我假设ComboBoxStyling.class..getResource(“ / css / styleclass.css”)可以工作-注意前导斜杠,以便相对于根找到它的位置
,而不是相对于ComboBoxStyling.class情况。所以我碰巧一起尝试了这种组合,并且奏效了!
private String getWords(){
String path = "/text/words.txt";
InputStream in = getClass().getResourceAsStream(path);
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
StringBuilder content = new StringBuilder();
try {
String line;
while( (line = reader.readLine()) != null) {
content.append(line);
}
} catch(IOException e){
e.printStackTrace();
}
return content.toString();
}