Getresourceasstream не видит файл в папке resources
В этой статье будет показано, как прочитать файл из папки “ресурсы”, “getResourceAsStream” или “getResource”.
Автор оригинала: mkyong.
В Java мы можем использовать getResourceAsStream или getResource для чтения файла или нескольких файлов из папки ресурсы или корневого каталога пути к классу.
Метод getResource возвращает URL и обычно преобразует его в Файл ; Не работает в файле JAR .
3 ответа
- Если имя начинается с «/» («\ u002f»), то абсолютное имя ресурса - это часть имени, следующая за «/».
- В противном случае абсолютное имя имеет следующую форму:
modified_package_name/name
Где имя_модуля_пакета - это имя пакета этого объекта с заменой '/' на '.' ( ' \ U002e ') .
Вот как я понимаю комментарии:
- Если вы используете ClassLoader.getResourceAsStream , отправьте абсолютный путь из корня пакета, но пропустите первый / .
- Если вы используете Class.getResourceAsStream , отправьте либо путь относительно текущего объекта Class (и метод примет пакет во внимание), либо отправьте абсолютный путь из корня пакета, начиная с > .
Но в дополнение к этому вы должны быть осведомлены о вашей системе сборки. В maven файлы ресурсов хранятся в src/main/resources .
Итак, в вашем случае, я считаю, что внесение следующих изменений должно решить проблему:
Измените код на
В качестве альтернативы используйте
Я пробовал это с подобной настройкой, и она работает, как ожидалось.
ClassLoader().getResourceAsStream() ищет файлы только в пути к классам. То, что вам нужно, это иметь ваш конфигурационный файл в каталоге, который находится в classpath.
Итак, у вас есть варианты:
Когда вы запускаете приложение Java из командной строки, вы можете указать путь к каталогу в параметре -cp или в системной переменной CLASSPATH. Дело в том, что каталог, из которого нужно получить файл конфигурации, должен находиться в пути к классам, а не в файле. (например, если местоположение файла c:\my_projects\test-project\config\my_config.properties и c:\my_projects\test-project\ находится в пути к классам, тогда getResourceAsStream вызов будет ClassLoader().getResourceAsStream("config/my_config.properties")
Вы можете упаковать свой файл в файл JAR, и корень файла JAR является отправной точкой для getResourceAsStream("config/my_config.properties")
Если ваш проект Maven является проектом jar, вам нужно использовать плагин ресурсов Maven, чтобы добавить дополнительные ресурсы в jar.
Кстати: Maven не помещает ничего в файл jar из каталога src / main / java / (если вы явно не указали это для плагина ресурсов)
Если вы используете IDE, например Eclipse, в своем проекте Maven, src / main / resources является частью пути к классам сборки. Дважды проверьте, есть ли оно, и если это не так - выполните «Обновить проект Maven» или добавьте его вручную.
Тем не менее ClassLoader будет видеть ваш файл свойств из папки src / main / resources только тогда, когда вы запускаете проект в IDE, а не из отдельного файла Jar - если вы не упаковали свой файл или не указали местоположение в classpath.
Можете ли вы попробовать следующий код.
Обновление: это код, который я пробовал.
И я поместил свойство table.config.txt файл с тестовым пакетом, и это сработало.
Я загружаю текстовый файл из пакета в скомпилированном JAR моего проекта Java. Соответствующая структура каталогов выглядит следующим образом:
Код для загрузки файла:
Распечатка всегда будет печатать null , независимо от того, что я использую. Я не уверен, почему это не сработало, поэтому я также пробовал:
- "/src/initialization/Lifepaths.txt"
- "initialization/Lifepaths.txt"
- "Lifepaths.txt"
Ни одна из этих работ не работает. Я прочитал questions до сих пор по этой теме, но ни один из них не был полезен – обычно они просто говорят, что загружают файлы с использованием корневого пути, который я уже делаю. Это или просто загрузите файл из текущего каталога (просто загрузите filename ), который я также попробовал. Файл скомпилируется в JAR в соответствующем месте с соответствующим именем.
Lifepaths.class.getClass().getResourceAsStream(. ) загружает ресурсы с помощью загрузчика системного класса, он явно терпит неудачу, потому что он не видит ваши JAR
Lifepaths.class.getResourceAsStream(. ) загружает ресурсы с использованием того же загрузчика классов, который загружал класс Lifepaths, и он должен иметь доступ к ресурсам в ваших JAR
- проверьте местоположение файла, который вы хотите загрузить внутри JAR (и, следовательно, также убедитесь, что он фактически добавлен в JAR)
- используйте либо абсолютный путь: путь начинается в корневом каталоге JAR
- использовать относительный путь: путь начинается в каталоге пакета класса, который вы вызываете getResource/getResoucreAsStream
(не уверен, что это имеет значение, но первый будет использовать правильный ClassLoader/JAR, в то время как я не уверен с последним)
Таким образом, есть несколько способов получить ресурс из банки, и каждый из них имеет немного другой синтаксис, где путь должен быть задан по-разному.
Лучшее объяснение, которое я видел, – это статья из JavaWorld. Я опишу здесь, но если вы хотите узнать больше, вы должны проверить статью.
Формат: “/” – разделенные имена; нет ведущего “/” (все имена являются абсолютными).
Формат: “/” – разделенные имена; ведущий “/” указывает абсолютные имена; все остальные имена относятся к пакету класса
Не используйте абсолютные пути, сделайте их относительно каталога ресурсов в вашем проекте. Быстрый и грязный код, отображающий содержимое MyTest.txt из ресурсов ресурса.
Возможно, вы захотите попробовать это, чтобы получить поток. Сначала получите URL-адрес, а затем откройте его как поток.
Кажется, что проблема с ClassLoader, который вы используете. Используйте contextClassLoader для загрузки класса. Это независимо от того, находится ли он в статическом/нестационарном методе
Я оказался в подобной проблеме. Поскольку я использую maven, мне нужно было обновить pom.xml, чтобы включить что-то вроде этого:
Обратите внимание на тег ресурса, чтобы указать, где находится эта папка. Если у вас есть вложенные проекты (например, я), вы можете захотеть получить ресурсы из других областей, а не только в том модуле, в котором работаете. Это помогает уменьшить сохранение одного и того же файла в каждом репо, если вы используете похожие данные конфигурации
Не знаю, нужна ли помощь, но в моем случае у меня был свой ресурс в папке/src/и я получал эту ошибку.
Затем я переместил изображение в папку bin и исправил проблему.
Убедитесь, что ваш каталог ресурсов (например, “src” ) находится в вашем пути к классу (убедитесь, что он является исходным каталогом в пути сборки в eclipse).
Убедитесь, что clazz загружен из основного загрузчика классов.
Затем, чтобы загрузить src/initialization/Lifepaths.txt, используйте
Почему:
clazz.getResourcesAsStream(foo) ищет foo из класса class clazz по сравнению с классом clazz, в котором живет. Ведущий “/” заставляет его загружать из корня любой директории в classpath clazz.
Если вы не находитесь в контейнере какого-то типа, например Tomcat, или делаете что-то с ClassLoaders напрямую, вы можете просто рассматривать свой путь класса eclipse/командной строки как единственный путь класса classloader.
Что сработало для меня, так это добавить файл в My Project/Java Resources/src, а затем использовать
Мне не нужно было объяснять добавление этого файла в путь (добавление его в /src делает это, по-видимому)
В моем случае ничего не получалось, если я не удалил пробелы из имен файлов…
Загрузчик классов JVM по умолчанию будет сначала использовать родительский загрузчик классов: .
Lifepaths.class.getClass() классов Lifepaths.class.getClass() является bootstrap classloader , поэтому getResourceAsStream будет искать только $ JAVA_HOME, независимо от предоставленного пользователем classpath . Очевидно, Lifepaths.txt не существует.
Lifepaths.class является system classpath classloader , поэтому getResourceAsStream будет искать пользовательский classpath и Lifepaths.txt там.
Предположим, структура вашего проекта выглядит следующим образом:
если вы используете Maven, убедитесь, что ваша упаковка – “баночка”, а не “пом”.
@Emracool… Я бы предложил вам альтернативу. Так как вы пытаетесь загрузить файл *.txt. Лучше использовать FileInputStream() , а не это раздражающее getClass().getClassLoader().getResourceAsStream() или getClass().getResourceAsStream() . По крайней мере, ваш код будет выполнен правильно.
Я загружаю текстовый файл из пакета в скомпилированный JAR моего проекта Java. Соответствующая структура каталогов выглядит следующим образом:
Мой код загружает файл, вызывая Class::getResourceAsStream для возврата InputStream .
Распечатка всегда будет напечатана null , независимо от того, что я использую. Я не уверен, почему это не сработает, поэтому я также пробовал:
- "/src/initialization/Lifepaths.txt"
- "initialization/Lifepaths.txt"
- "Lifepaths.txt"
Ни то, ни другое не работает. Я прочитал множество вопросов по этой теме, но ни один из них не помог - обычно они просто говорят загружать файлы, используя корневой путь, что я уже делаю. Это или просто загрузить файл из текущего каталога (просто загрузить filename ), что я тоже пробовал. Файл компилируется в JAR в соответствующем месте с соответствующим именем.
Как мне решить эту проблему?
@greedybuddha Хотя я не могу вызвать это из статического контекста, я могу вызвать его с помощью Lifepaths.class . При этом, почему это getClassLoader() позволяет ему работать? (Кроме того, не стесняйтесь публиковать ответ!)
Взгляните на этот ответ и посмотрите, сможете ли вы заставить его работать getResource(String) . Кстати, у меня всегда были проблемы с тем, чтобы заставить кого-то из них работать в static контексте. Проблема в основном в том, что полученный загрузчик классов предназначен для классов J2SE. Вам необходимо получить доступ к загрузчику классов контекста, который предназначен для самого приложения.
Lifepaths.class.getClass().getResourceAsStream(. ) загружает ресурсы с помощью загрузчика системных классов, он явно не работает, потому что не видит ваши JAR-файлы
Lifepaths.class.getResourceAsStream(. ) загружает ресурсы, используя тот же загрузчик классов, который загружал класс Lifepaths, и он должен иметь доступ к ресурсам в ваших JAR-файлах
Просто чтобы добавить: при вызове getResourceAsStream (name) имя должно начинаться с «/». Я не уверен, нужно ли это, но без этого у меня проблемы.
Я занимаюсь этим с 8 утра сегодня / вчера утром. Спас меня. Мне также нужна была косая черта, чтобы это работало.
Также имейте в виду, что желаемый источник может находиться вне иерархии пакетов. В этом случае вам нужно будет использовать "../" на вашем пути, чтобы подняться на один уровень, а затем вниз к другой ветви пути, чтобы добраться до вашего ресурса.
@David - я думаю, что это (ведущее '/') необходимо, иначе поиск будет происходить относительно пакета Lifepaths.class.
Просто чтобы добавить некоторую информацию, вам нужно добавить / перед вашим путем, если ваш файл находится в другом каталоге; например initialization/Lifepaths.txt . Если путь к файлу совпадает с вашим классом (но в разделе ресурсов как основной каталог), вы можете просто указать имя файла без него / . Например, если ваш класс имеет следующий путь src/main/java/paths/Lifepaths.java , ваш файл должен иметь этот путь src/main/resources/paths/Lifepaths.txt .
- проверьте расположение файла, который вы хотите загрузить, внутри JAR (и, таким образом, также убедитесь, что он действительно добавлен в JAR)
- используйте либо абсолютный путь: путь начинается с корня JAR
- используйте относительный путь: путь начинается в каталоге пакета класса, который вы вызываете getResource / getResoucreAsStream
(не уверен, имеет ли это значение, но первый будет использовать правильный ClassLoader / JAR, а я не уверен в последнем)
Из вашего вопроса неясно, что такое «Соответствующая структура каталогов», и если вы действительно проверили, находится ли файл в JAR и где (шаг 1)
Интересно. Оказывается, мне пришлось сделать "/config.properties" (с косой чертой), чтобы добраться до него .
Таким образом, есть несколько способов получить ресурс из jar-файла, и каждый из них имеет немного другой синтаксис, в котором путь нужно указывать по-разному.
Лучшее объяснение, которое я видел, - это статья из InfoWorld . Я резюмирую здесь, но если вы хотите узнать больше, вам следует почитать статью.
Формат: «/» - имена через разделитель; без начального символа "/" (все имена абсолютны).
Формат: «/» - имена через разделитель; "/" в начале указывает абсолютные имена; все остальные имена относятся к пакету класса
Обновлено сентябрь 2020 г .: изменена ссылка на статью. Оригинальная статья была из Javaworld, теперь она размещена на InfoWorld (и имеет еще много рекламы)
Также: убедитесь, что ваша IDE видит файл ('some / pkg / resource.properties'), обновив исходную папку.
В случае, если это кому-то поможет, рут для меня / target / classes. Поэтому, если я загружаю файл test.json первым методом, он должен находиться в /target/classes/test.json в скомпилированном коде или соответствующем файле jar.
Не используйте абсолютные пути, сделайте их относительными к каталогу ресурсов в вашем проекте. Быстрый и грязный код, отображающий содержимое MyTest.txt из каталога "ресурсы".
Вы можете попробовать это, чтобы получить поток, т.е. сначала получить URL-адрес, а затем открыть его как поток.
Я оказался в похожей проблеме. Поскольку я использую maven, мне нужно обновить мой pom.xml, чтобы включить что-то вроде этого:
Обратите внимание на тег ресурса, чтобы указать, где находится эта папка. Если у вас есть вложенные проекты (например, у меня), вы можете захотеть получить ресурсы из других областей, а не только в модуле, в котором вы работаете. Это помогает уменьшить хранение одного и того же файла в каждом репо, если вы используете аналогичные данные конфигурации.
Кажется, проблема с используемым вами ClassLoader. Используйте contextClassLoader для загрузки класса. Это независимо от того, находится ли он в статическом / нестатическом методе
Предположим, структура вашего проекта выглядит следующим образом:
JVM Загрузчик классов по умолчанию будет использовать родительский-загрузчик классов для первой загрузки ресурсов: .
Lifepaths.class.getClass() загрузчик классов есть bootstrap classloader , поэтому getResourceAsStream будет искать только $ JAVA_HOME, независимо от пользователя classpath . Очевидно, Lifepaths.txt там нет.
Lifepaths.class загрузчик классов есть system classpath classloader , поэтому getResourceAsStream поиск будет определяться пользователем, classpath а Lifepaths.txt находится там.
Я загружаю текстовый файл из пакета в скомпилированный JAR моего проекта Java. Соответствующая структура каталогов выглядит следующим образом:
Мой код загружает файл, вызывая Class::getResourceAsStream для возврата InputStream .
Распечатка всегда будет напечатана null , независимо от того, что я использую. Я не уверен, почему это не сработает, поэтому я также пробовал:
- "/src/initialization/Lifepaths.txt"
- "initialization/Lifepaths.txt"
- "Lifepaths.txt"
Ни то, ни другое не работает. Я прочитал множество вопросов по этой теме, но ни один из них не помог - обычно они просто говорят загружать файлы с использованием корневого пути, что я уже делаю. Это или просто загрузить файл из текущего каталога (просто загрузить filename ), что я тоже пробовал. Файл компилируется в JAR в соответствующем месте с соответствующим именем.
Как мне решить эту проблему?
@greedybuddha Хотя я не могу вызвать это из статического контекста, я могу вызвать его с помощью Lifepaths.class . При этом, почему это getClassLoader() позволяет ему работать? (Кроме того, не стесняйтесь публиковать ответ!)
Взгляните на этот ответ и посмотрите, сможете ли вы заставить его работать getResource(String) . Кстати, у меня всегда были проблемы с тем, чтобы заставить кого-то из них работать в static контексте. Проблема в основном в том, что полученный загрузчик классов предназначен для классов J2SE. Вам необходимо получить доступ к загрузчику классов контекста, который предназначен для самого приложения.
Lifepaths.class.getClass().getResourceAsStream(. ) загружает ресурсы с помощью загрузчика системных классов, он явно не работает, потому что не видит ваши JAR-файлы
Lifepaths.class.getResourceAsStream(. ) загружает ресурсы, используя тот же загрузчик классов, который загружал класс Lifepaths, и он должен иметь доступ к ресурсам в ваших JAR-файлах.
Просто чтобы добавить: при вызове getResourceAsStream (name) имя должно начинаться с «/». Я не уверен, нужно ли это, но без этого у меня проблемы.
Я занимаюсь этим с 8 утра сегодня / вчера утром. Спас меня. Мне также нужна была косая черта, чтобы это работало.
Также имейте в виду, что желаемый источник может находиться вне иерархии пакетов. В этом случае вам нужно будет использовать "../" на вашем пути, чтобы подняться на один уровень, а затем вниз к другой ветви пути, чтобы добраться до вашего ресурса.
@David - я думаю, что это (ведущее '/') необходимо, иначе поиск будет происходить относительно пакета Lifepaths.class.
Просто чтобы добавить некоторую информацию, вам нужно добавить / перед вашим путем, если ваш файл находится в другом каталоге; например initialization/Lifepaths.txt . Если путь к файлу совпадает с вашим классом (но в разделе ресурсов как основной каталог), вы можете просто указать имя файла без него / . Например, если ваш класс имеет следующий путь src/main/java/paths/Lifepaths.java , ваш файл должен иметь этот путь src/main/resources/paths/Lifepaths.txt .
- проверьте расположение файла, который вы хотите загрузить, внутри JAR (и, таким образом, также убедитесь, что он действительно добавлен в JAR)
- используйте либо абсолютный путь: путь начинается с корня JAR
- используйте относительный путь: путь начинается в каталоге пакета класса, который вы вызываете getResource / getResoucreAsStream
(не уверен, имеет ли это значение, но первый будет использовать правильный ClassLoader / JAR, а со вторым я не уверен)
Из вашего вопроса неясно, что такое «Соответствующая структура каталогов», и если вы действительно проверили, находится ли файл в JAR и где (шаг 1)
Интересно. Оказывается, мне пришлось сделать "/config.properties" (с косой чертой), чтобы добраться до него .
Таким образом, есть несколько способов получить ресурс из jar-файла, и каждый из них имеет немного другой синтаксис, в котором путь нужно указывать по-разному.
Лучшее объяснение, которое я видел, - это статья из InfoWorld . Я резюмирую здесь, но если вы хотите узнать больше, вам следует почитать статью.
Формат: «/» - имена через разделитель; без начального символа "/" (все имена абсолютны).
Формат: «/» - имена через разделитель; "/" в начале указывает абсолютные имена; все остальные имена относятся к пакету класса
Обновлено сентябрь 2020 г .: изменена ссылка на статью. Оригинальная статья была из Javaworld, теперь она размещена на InfoWorld (и имеет еще много рекламы)
Также: убедитесь, что ваша IDE видит файл ('some / pkg / resource.properties'), обновив исходную папку.
В случае, если это кому-то поможет, рут для меня / target / classes. Поэтому, если я загружаю файл test.json первым методом, он должен находиться в /target/classes/test.json в скомпилированном коде или соответствующем файле jar.
Не используйте абсолютные пути, сделайте их относительными к каталогу ресурсов в вашем проекте. Быстрый и грязный код, отображающий содержимое MyTest.txt из каталога "ресурсы".
Вы можете попробовать это, чтобы получить поток, т.е. сначала получить URL-адрес, а затем открыть его как поток.
Я оказался в похожей проблеме. Поскольку я использую maven, мне нужно обновить мой pom.xml, чтобы включить что-то вроде этого:
Обратите внимание на тег ресурса, чтобы указать, где находится эта папка. Если у вас есть вложенные проекты (например, у меня), вы можете захотеть получить ресурсы из других областей, а не только в модуле, в котором вы работаете. Это помогает уменьшить хранение одного и того же файла в каждом репо, если вы используете аналогичные данные конфигурации.
Кажется, проблема с используемым вами ClassLoader. Используйте contextClassLoader для загрузки класса. Это независимо от того, находится ли он в статическом / нестатическом методе
Предположим, структура вашего проекта выглядит следующим образом:
JVM Загрузчик классов по умолчанию будет использовать родительский-загрузчик классов для первой загрузки ресурсов: .
Lifepaths.class.getClass() загрузчик классов есть bootstrap classloader , поэтому getResourceAsStream будет искать только $ JAVA_HOME, независимо от пользователя classpath . Очевидно, Lifepaths.txt там нет.
Lifepaths.class загрузчик классов есть system classpath classloader , поэтому getResourceAsStream поиск будет определяться пользователем, classpath а Lifepaths.txt находится там.
2. Получите файл из папки ресурсов.
2.1 Приведенный ниже пример демонстрирует использование getResourceAsStream и getResource методы чтения файла json/файл 1.json из папки ресурсы
- Метод getResource не работает в файле JAR.
- Метод getResourceAsStream работает везде.
2.2 Теперь мы упаковываем проект в файл JAR и запускаем его; на этот раз getResource завершится ошибкой и вернет либо Исключение NoSuchFileException , либо Исключение InvalidPathException . Мы не можем прочитать файлы внутри файла JAR по URL-адресу ресурса.
Запустите файл JAR в Linux (Ubuntu), он вызовет Исключение NoSuchFileException .
Запустите файл JAR в Windows, он вызовет Исключение InvalidPathException .
P.S В этом примере используется плагин Maven maven-jar-плагин чтобы создать файл JAR.
4. Получите все файлы из папки ресурсов. (Среда, ОТЛИЧНАЯ от JAR)
Если мы не знаем точного имени файла и хотим прочитать все файлы, включая файлы вложенных папок из папки ресурсов, мы можем использовать NIO Файлы.перейдите , чтобы легко получить доступ к файлам и прочитать их.
4.1 В приведенном ниже примере используются Файлы.пройдите чтобы прочитать все файлы из папки src/основные/ресурсы/json :
4.2 Однако стандартные Файлы.прогулка в примере 4.1 не удается получить доступ к файлам в файле JAR напрямую, попробуйте запустить пример 4.1 в среде JAR, и он выдает Исключение FileSystemNotFoundException .
1. Файлы в ресурсах папка
1.1 Просмотрите файлы в src/main/ресурсы , позже мы получим доступ к файлам и распечатаем содержимое файла.
1.2 По умолчанию инструменты сборки, такие как Maven, Gradle или обычная практика Java, будут копировать все файлы из src/основные/ресурсы в корневой каталог целевые/классы или сборка/классы . Итак, когда мы пытаемся прочитать файл из src/main/ресурсы , мы читаем файл из корневого каталога пути к классам проекта.
1.3 Ниже приведена структура файла JAR. Обычно файлы в папке ресурсы копируются в корневой каталог пути к классу.
5. Получите все файлы из папки ресурсов. (Версия JAR)
5.1 В этом примере показано, как Файлы.перейдите в папку внутри файла JAR через Файловые системы и URI jar:файл: xxx.jar .
Я знаю, что этот вопрос задавался несколько раз, но я все еще не могу заставить его работать этими решениями.
У меня есть проект Maven. И один файл Config.java, расположенный в consumer/src/main/java . Вот содержание:
Я продолжал получать nullpointer exception . Я знаю, это потому, что он не может найти файл property_table.config.txt .
Сначала я поместил файл property_table_config.txt в ту же папку ( consumer/src/main/java/ ), что и файл Config.java. И попытался использовать /property_table_config.txt и 'property_table_config.txt`. Ни один из них не работает.
А затем я попытался использовать абсолютный путь, но не работал. И попытался использовать /main/java/property_table_config , тоже не работает.
Но это все еще не сработало. Кто-нибудь может дать намек на это? Любые предложения будут оценены!
3. Получите файл из папки ресурсов – Модульный тест
3.1 Мы помещаем тестовые ресурсы в папку src/test/ресурсы для модульных тестов. Обычно файлы в тестовых ресурсах копируются в папку target/test-classes .
3.2 Это работает так же, как мы читаем файл из src/main/ресурсы . Мы используем то же самое getResourceAsStream и getResource методы чтения файла из src/test/ресурсов .
Читайте также: