Java ClassLoader.getResourceAsStream (путь) возвращает значение null, когда ресурс находится внутри вложенной банки

Мой проект Springboot (проект A) зависит от библиотеки (библиотеки B), которая представляет собой файл jar (это также мой проект, но исходный код отсутствует во время проекта компиляции A). Внутри jar у меня есть каталог dir1 с одним файлом file2.

Структура проекта:

- project A
-- src/main/java/com/test/ResourcesUtils.java
-- src/main/resources/dir1/file1

- library B
-- src/main/resources/dir1/file2

Когда я пытаюсь получить ресурс из проекта A, все работает нормально, например:

InputStream is1 = ResourcesUtils.class.getClassLoader().getResourceAsStream("dir1\\file1);
InputStream is2 = ResourcesUtils.class.getClassLoader().getResourceAsStream("dir1/file1);

Оба (is1, is2) не равны нулю.

Когда я пытаюсь получить ресурс из библиотеки B, используя тот же метод, он не работает.

InputStream is1 = ResourcesUtils.class.getClassLoader().getResourceAsStream("dir1\\file2);
InputStream is2 = ResourcesUtils.class.getClassLoader().getResourceAsStream("dir1/file2);

Переменная is1 равна нулю, is2 не равна нулю.

Я делаю что-то неправильно? Почему он работает иначе для ресурса из основной банки, чем для зависимой банки?

Я не могу просто переключиться на вторую версию (с помощью '/', потому что я не контролирую строку, которая передается в getResourceAsStream)

public static boolean existsInResource(Path path) {

try (InputStream is = ResourcesUtils.class.getClassLoader().getResourceAsStream(path.toString())) {
      return is != null;
    } catch (final IOException e) {
      // handle exception
    }
  }

В моем коде, который работает, в пути используется косая черта. Подобные проблемы всегда заключаются в том, что у вас не совсем правильный путь. Я думаю, вы хотите /main/resources/dir1/file1.

Gene 02.04.2022 18:31

Путь в порядке, он работает с «/», но не работает с «\» в качестве разделителя пути. В банке библиотеки dir1 находится на корневом пути, поэтому мне не нужно добавлять «/main/resources...» и т. д.

Piotr S 02.04.2022 18:57

API задокументировано для использования / в качестве разделителя, а не \. Вы упоминаете, что не можете просто переключиться на использование первого, потому что «я не контролирую строку, которая передается в getResourceAsStream». Но я предполагаю, что вам разрешено обрабатывать строку перед передачей ее в качестве аргумента, не так ли? Потому что, если вы можете, то один из вариантов — сделать path = path.replace('\\', '/'), чтобы заменить обратную косую черту на прямую косую черту.

Slaw 02.04.2022 19:11

Да, я могу, но я подумал, что это должно работать и с '\'. Спасибо за ваши ответы и ссылки на документацию. Вы спасли мой день :)

Piotr S 02.04.2022 19:18
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
0
4
36
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Когда речь идет о file1,, это физический файл в вашем приложении, и я предполагаю, что вы запускаете свой код в Windows. Файл file1 находится в файловой системе Windows.

Когда речь идет о file2, он находится внутри файла JAR. Это не файловая система Windows, это файл JAR.

Если вы не знаете, что это физический файл, безопаснее использовать прямую косую черту. \ — это остаток от старых 32-битных окон до Windows NT. Windows NT внутри (я не уверен, правильно ли я помню) использует /, а командный процессор использует только \.

Вы, конечно, правы относительно того, почему использование \ ломается после упаковки в файл JAR. Но это касается деталей реализации. Есть более простая причина для использования всегда/: Поскольку API задокументировано использует / в качестве разделителя.

Slaw 02.04.2022 19:06

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