Я загружаю текстовый файл из пакета в скомпилированном JAR моего Java-проекта. Соответствующая структура каталогов выглядит следующим образом:
/src/initialization/Lifepaths.txt
Код, используемый для загрузки файла, следующий:
public class Lifepaths {
public static void execute() {
System.out.println(Lifepaths.class.getClass().
getResourceAsStream("/initialization/Lifepaths.txt"));
}
private Lifepaths() {}
//This is temporary; will eventually be called from outside
public static void main(String[] args) {execute();}
}
На печать всегда выводится null
, независимо от того, что я использую. Я'не уверен, почему вышеупомянутое не работает, поэтому я'также попробовал:
"initialization/Lifepaths.txt"
"Lifepaths.txt"
Ни один из этих вариантов не работает. I've read numerous questions so far on the topic, but none of them have been helpful - usually, they just say to load files using the root path, which I'm already doing. Это, или просто загрузить файл из текущего каталога (просто load filename
), что я'также пробовал. Файл компилируется в JAR в соответствующем месте с соответствующим именем.
Как мне решить эту проблему?
Lifepaths.class.getClass().getResourceAsStream(...)
загружает ресурсы с помощью системного загрузчика классов, очевидно, что это не удается, поскольку он не видит ваши JAR-файлы
Lifepaths.class.getResourceAsStream(...)
загружает ресурсы, используя тот же загрузчик классов, который загрузил класс Lifepaths, и он должен иметь доступ к ресурсам в ваших JAR-ах
Правила следующие:
И попробуйте:
Lifepaths.class.getResourceAsStream("/initialization/Lifepaths.txt")
вместо
Lifepaths.class.getClass().getResourceAsStream("/initialization/Lifepaths.txt")
(не уверен, что это имеет значение, но первый будет использовать правильный ClassLoader/ JAR, в то время как я не уверен во втором)
Таким образом, существует несколько способов получить ресурс из jar, и каждый из них имеет немного отличающийся синтаксис, где путь должен быть указан по-разному.
Лучшее объяснение, которое я видел, это статья из JavaWorld. Я подытожу здесь, но если вы хотите узнать больше, вам следует ознакомиться со статьей.
Методы
ClassLoader.getResourceAsStream()
. Формат: "/"-разделенные имена; без ведущих "/" (все имена абсолютные).
Пример: this.getClass().getClassLoader().getResourceAsStream("some/pkg/resource.properties");
.
Class.getResourceAsStream()
.Формат: "/"-разделенные имена; ведущее "/" указывает на абсолютные имена; все остальные имена являются относительными к классу'пакету
Пример: this.getClass().getResourceAsStream("/some/pkg/resource.properties");
.
Не используйте абсолютные пути, сделайте их относительными к директории 'resources' в вашем проекте. Быстрый и грязный код, который отображает содержимое файла MyTest.txt из каталога 'resources'.
@Test
public void testDefaultResource() {
// can we see default resources
BufferedInputStream result = (BufferedInputStream)
Config.class.getClassLoader().getResourceAsStream("MyTest.txt");
byte [] b = new byte[256];
int val = 0;
String txt = null;
do {
try {
val = result.read(b);
if (val > 0) {
txt += new String(b, 0, val);
}
} catch (IOException e) {
e.printStackTrace();
}
} while (val > -1);
System.out.println(txt);
}
Вы можете попробовать это, чтобы получить поток я.е сначала нужно получить URL-адрес и затем открыть его как поток.
URL url = getClass().getResource("/initialization/Lifepaths.txt");
InputStream strm = url.openStream();
Я когда-то был подобный вопрос: https://stackoverflow.com/questions/16563622/reading-txt-file-from-jar-fails-but-reading-image-works/16564611#16564611
Там, кажется, проблема с classloader, который вы используете. Используйте contextClassLoader для загрузки класса. Это независимо от того, является ли он в статическом/нестатический метод
Резьба.currentThread().getContextClassLoader().методаgetresourceasstream
......
Я оказался в подобной проблеме. Так как я с помощью Maven мне нужно обновить pom.xml включить что-то вроде этого:
...
</dependencies>
<build>
<resources>
<resource>
<directory>/src/main/resources</directory>
</resource>
<resource>
<directory>../src/main/resources</directory>
</resource>
</resources>
<pluginManagement>
...
Обратите внимание на метки ресурса там, чтобы указать, где эта папка находится. Если у вас есть вложенные проекты (как я), то вы, возможно, захотите, чтобы получить ресурсы из других областей, а не только в модуле, в котором вы работаете. Это помогает уменьшить сохраняя тот же файл в каждой сделки РЕПО при использовании подобных данных конфигурации
Убедитесь, что ваш каталог ресурсов (например, на "НИЦ", у) находится в вашем classpath (убедитесь, что он's для исходного каталога в свой путь сборки в Eclipse).
Убедитесь, что clazz загружается из главного загрузчика.
Затем для загрузки src/initialization/Lifepaths.txt используйте
clazz.getResourceAsStream("/initialization/Lifepaths.txt");
Почему:
clazz.getResourcesAsStream(ФОО)
ищет Foo из в пределах класса clazz, по отношению к жизни clazz каталог в. Ведущих и"/" и делает его загрузить из корня любой каталог в classpath clazz.
Если вы're в контейнер какой-то, как Tomcat или делаете что-то с загрузчиками классов напрямую, вы можете просто относитесь к своим затмение/командной строке путь к классу, как только загрузчиком классов.
Дон'т знать, если помогают, но в моем случае у меня был свой ресурс в папке /src/ и получал эту ошибку. Затем я переместил картинку в папку bin и исправили проблему.
Грубо говоря:
getClass().методу getresource (и"/", у)
нить~=.currentThread().getContextClassLoader().методу getresource (и".&и")
Предположим, структура проекта, как следующее:
`` ├── ГРЦ │ ├── главная │ └── тест │ испытания └── │ ├── Ява │ │ └── ком │ │ └── на GitHub │ │ └── АБВ │ │ └── прое │ │ ├── MainTest.java │ │ └── TestBase.java │ └── ресурсов │ └── abcd.txt └── целевые тест-классы └── ├── сом └── abcd.txt
``
`` // в MainClass.java это.getClass.ГТ; и quot методу getresource(" в/то") -&;~/proj_dir/целевой/тест-классы/"по это.getClass.методу getresource (и".&и") -> и"~/proj_dir/целевой/тест-классы/ком/гитхаб/ской/прое/с" Нить.currentThread().getContextClassLoader().getResources (и".&и") -> и"~/proj_dir/целевой/тест-классы/"и Нить.currentThread().getContextClassLoader().getResources(" в/то") -> нуль
``
Что работал для меня было, чтобы добавить файл в мой проект/ресурсы Java/src и потом использовать
this.getClass().getClassLoader().getResourceAsStream(myfile.txt);
Я не'т должны явным образом добавить этот файл в путь (при добавлении его в /ГРЦ это очевидно)
JVM по умолчанию classloader-загрузчик будет использовать родитель-classloader загрузить ресурсы в первую очередь:
.
Lifepaths.класс.getClass()
'с загрузчиком это загрузчик загрузчика классов, поэтому
методаgetresourceasstreamбудет искать только $переменной JAVA_HOME, независимо от пользователя при условии
классов`. Очевидно, Lifepaths.txt нет.
Lifepaths.class
'ы classloader является путь к классу системного загрузчика классов
, так методаgetresourceasstream
поиск пользовательских классов
и Lifepaths.txt есть.
При использовании Ява.яз.Класс#методаgetresourceasstream(имя строки), имя которого не начинается с **'/'** будет добавлено имя пакета в качестве префикса. Если вы хотите избежать этого, пожалуйста, используя
Ява.яз.Класслоадер#методаgetresourceasstream`.
Например:
Ява Загрузчиком загрузчик = нить.currentThread().getContextClassLoader(); Строки имя_ресурса = "и Lifepaths.тхт и"; ResourceStream класса InputStream = загрузчик.методаgetresourceasstream(имя_ресурса);
@Emracool... я'd предлагает вам альтернативу. Поскольку вы, кажется, пытаюсь загрузить *.файл txt. Лучше использовать FileInputStream (), а затем getClass это раздражает ().getClassLoader().getresourceasstream (), как
или getClass().getresourceasstream (), как
. По крайней мере, ваш код будет выполняться правильно.