Сбой загрузки классов в подкаталоге с модульным JavaFX - PullRequest
1 голос
/ 26 марта 2020

Я создал проект Gradle, который использует загрузчик классов для загрузки текстового файла из подкаталога resources / text. На данный момент это работает, но когда я преобразую проект в модульную программу JavaFX, та же функция загрузчика классов дает исключение NullPointerException.

src / основной каталог проекта

└───src
    └───main
        ├───java
        │   │   module-info.java
        │   └───app
        │           Main.java
        └───resources
            └───text
                    words.txt

build.gradle

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-info. java

module exMod {
    requires javafx.controls;
    exports app;
}

Main. java

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 и как я могу это исправить?

1 Ответ

1 голос
/ 26 марта 2020

В комментарии к этот вопрос , в качестве альтернативы program.class.getClassLoader().getResource("b/text.txt") пользователь Хольгер заявляет

... вы должны использовать program.class.getResource("b/text.txt"), чтобы разрешить ресурс относительно расположения класса программы. В противном случае может произойти сбой в Java 9 или новее после использования модулей, так как переход к загрузчику классов уничтожит информацию о реальном модуле.

Из-за этого я попытался использовать просто getClass().getResourceAsStream(path) вместо getClass().getClassLoader().getResourceAsStream(path).

Я также читал комментарий Алана Бейтмена по поводу этого вопроса , где он сообщает

Ресурс инкапсулирован, поэтому он может не может быть найдено с API ClassLoader. Я предполагаю, что ComboBoxStyling.class..getResource ("/ css / styleclass. css") будет работать - обратите внимание на ведущий sla sh, так что он найден относительно расположения root модуля , не относящийся к классу ComboBoxStyling.class в этом случае.

Так что мне довелось попробовать эту комбинацию вместе, и она сработала!

getWords ()

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();
    }
...