Как получить доступ к ресурсам в папке внешних ресурсов в модульном проекте Java 9

Когда у меня есть следующий код, который пытается получить доступ к ресурсу:

foo / Main.java

package foo;
import java.io.*;

public class Main{
    public static void main(String... args) throws IOException{
        try(BufferedReader in = new BufferedReader(new InputStreamReader(
                            Main.class.getClassLoader().getResourceAsStream("foo/res.txt")))){
            for(String line = in.readLine(); line!=null; line=in.readLine()){
                System.out.println("Line : " + line);
            }
            System.out.println("EOF");
        }
    }
}

скомпилируйте это:

javac foo/Main.java -d build/classes/

и добавьте файл ресурсов, тогда я получу что-то вроде этого:

foo/
|--Main.java
`--build
   |--classes
   |  `--foo
   |     `--Main.class
   `--resources
      `--foo
         `--res.txt

и после запуска, выполнив следующую команду:

java -cp "build/classes:build/resources" foo.Main

Я получу ожидаемый результат, например:

Line : This is a
Line : test!
EOF

Но проблема возникает, когда я делаю проект модульным. Я добавил простейший module-info.java вот так:

module-info.java

module bar {
}

и скомпилируйте его:

javac foo/Main.java module-info.java -d build/classes/

тогда я получу следующую файловую структуру:

module-info.java
foo/
|--Main.java
`--build
   |--classes
   |  |--module-info.class
   |  `--foo
   |     `--Main.class
   `--resources
      `--foo
         `--res.txt

Но когда я выполняю класс, набирая команду

java -p "build/classes/;build/resources/" -m bar/foo.Main

Я получаю сообщение об ошибке, в котором говорится, что ресурс не найден.

Exception in thread "main" java.lang.NullPointerException
        at java.base/java.io.Reader.<init>(Reader.java:167)
        at java.base/java.io.InputStreamReader.<init>(InputStreamReader.java:72)
        at bar/foo.Main.main(Main.java:7)

Как я могу получить доступ к ресурсам изнутри модуля?

Редактировать: Обратите внимание, что в этом вопросе конкретно задается вопрос, как получить доступ к ресурсам в «развернутом» модуле (модуле, который не был упакован как файл JAR). Ключевой деталью здесь является то, что в разнесенном модуле папка ресурсов не рассматривается автоматически как часть модуля, если специально не исправлено в командной строке в соответствии с комментарием @Alan Bateman.

Это делает вопрос не дубликатом "Головоломка Java 9 - доступ к файлам ресурсов из внешних модулей". Этот вопрос включает в себя предоставление доступа к файлам ресурсов от одного неразорванного модуля другому неразорванному модулю.

Этот вопрос тоже не дублирует "Как работать с ресурсами в модулях Java 9". Этот вопрос связан с ситуацией, когда один «главный» модуль не может получить доступ к ресурсам, связанным с тестированием, размещенным в нем с помощью «--add-patch», из-за того, что папки ресурсов, связанных с тестированием, не включаются в Gradle.

Этот вопрос тоже не дублирует "Расположение файлов системных ресурсов модуля Java 9". Этот вопрос включает в себя, как заставить модуль обращаться к папке ресурсов, которая находится за пределами собственного исходного дерева модуля.

Существующий вопрос, который, вероятно, наиболее близок к дублированию, - это, вероятно, «Куда попадают файлы ресурсов в проекте Gradle, который создает модуль Java 9?», Который подробно описывает пару связанных сценариев и его стоит прочитать, если у вас возникли проблемы с этой проблемой.

Вам нужна команда java -p build/classes --patch-module m=build/resources -m bar/foo.Main. Это связано с тем, что разнесенный модуль требует, чтобы классы и ресурсы модуля находились в одном дереве каталогов. У вас не возникнет этой проблемы, когда вы упакуете модуль как файл JAR, поскольку классы и ресурсы будут в файле JAR.

Alan Bateman 27.10.2018 09:37

Спасибо за ваш ответ. Я искал в Google, но не смог найти вариант --patch-module, это очень помогло. Я уверен, что в данном случае мне нужна настоящая команда java -p build/classes --patch-module bar=build/resources -m bar/foo.Main, потому что я должен указать имя моего модуля в опции --patch-module. Однако он по-прежнему не работает и выдает тот же NPE, что ресурс не был найден. В какой момент я ошибаюсь?

user3917751 28.10.2018 05:35

Да, опечатка в комментарии, это должен был быть --patch-module bar=build/resources для исправления панели модулей, чтобы включить ресурсы в дерево сборки / ресурсов. Другая проблема заключается в том, что код должен быть Main.class.getResourceAsStream ("res.txt") или Main.class.getResourceAsStream ("/ foo / res.txt"). Это связано с тем, что модули по умолчанию инкапсулируют свои ресурсы.

Alan Bateman 28.10.2018 08:39

Это сработало!! Большое спасибо, и мне очень жаль, что я опубликовал повторяющийся вопрос. Я не знал, что есть два способа получить ресурсы ...

user3917751 29.10.2018 13:52

@nullpointer, можешь ли ты вызвать по этой мете по твоему дублирующему голосу meta.stackoverflow.com/q/376384/578411

rene 08.11.2018 14:35
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
0
5
1 665
0

Другие вопросы по теме