Мой проект 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
}
}
Путь в порядке, он работает с «/», но не работает с «\» в качестве разделителя пути. В банке библиотеки dir1 находится на корневом пути, поэтому мне не нужно добавлять «/main/resources...» и т. д.
API задокументировано для использования /
в качестве разделителя, а не \
. Вы упоминаете, что не можете просто переключиться на использование первого, потому что «я не контролирую строку, которая передается в getResourceAsStream». Но я предполагаю, что вам разрешено обрабатывать строку перед передачей ее в качестве аргумента, не так ли? Потому что, если вы можете, то один из вариантов — сделать path = path.replace('\\', '/')
, чтобы заменить обратную косую черту на прямую косую черту.
Да, я могу, но я подумал, что это должно работать и с '\'. Спасибо за ваши ответы и ссылки на документацию. Вы спасли мой день :)
Когда речь идет о file1,
, это физический файл в вашем приложении, и я предполагаю, что вы запускаете свой код в Windows. Файл file1
находится в файловой системе Windows.
Когда речь идет о file2
, он находится внутри файла JAR. Это не файловая система Windows, это файл JAR.
Если вы не знаете, что это физический файл, безопаснее использовать прямую косую черту. \
— это остаток от старых 32-битных окон до Windows NT. Windows NT внутри (я не уверен, правильно ли я помню) использует /
, а командный процессор использует только \
.
Вы, конечно, правы относительно того, почему использование \
ломается после упаковки в файл JAR. Но это касается деталей реализации. Есть более простая причина для использования всегда/
: Поскольку API задокументировано использует /
в качестве разделителя.
В моем коде, который работает, в пути используется косая черта. Подобные проблемы всегда заключаются в том, что у вас не совсем правильный путь. Я думаю, вы хотите
/main/resources/dir1/file1
.