GetResourceAsStream возвращает null
Я загружаю текстовый файл из пакета в скомпилированном 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
, независимо от того, что я использую. Я не уверен, почему это не сработало, поэтому я также пробовал:
-
"/src/initialization/Lifepaths.txt"
-
"initialization/Lifepaths.txt"
-
"Lifepaths.txt"
Ни одна из этих работ не работает. Я прочитал questions до сих пор по этой теме, но ни один из них не был полезен - обычно они просто говорят, что загружают файлы с использованием корневого пути, который я уже делаю. Это или просто загрузите файл из текущего каталога (просто загрузите filename
), который я также попробовал. Файл скомпилируется в JAR в соответствующем месте с соответствующим именем.
Как это решить?
Ответы
Ответ 1
Lifepaths.class.getClass().getResourceAsStream(...)
загружает ресурсы с помощью загрузчика системного класса, он явно терпит неудачу, потому что он не видит ваши JAR
Lifepaths.class.getResourceAsStream(...)
загружает ресурсы с использованием того же загрузчика классов, который загружал класс Lifepaths, и он должен иметь доступ к ресурсам в ваших JAR
Ответ 2
Правила следующие:
- проверьте местоположение файла, который вы хотите загрузить внутри JAR (и, следовательно, также убедитесь, что он фактически добавлен в JAR)
- используйте либо абсолютный путь: путь начинается в корневом каталоге JAR
- использовать относительный путь: путь начинается в каталоге пакета класса, который вы вызываете getResource/getResoucreAsStream
И попробуйте:
Lifepaths.class.getResourceAsStream("/initialization/Lifepaths.txt")
вместо
Lifepaths.class.getClass().getResourceAsStream("/initialization/Lifepaths.txt")
(не уверен, что это имеет значение, но первый будет использовать правильный ClassLoader/JAR, в то время как я не уверен с последним)
Ответ 3
Таким образом, есть несколько способов получить ресурс из банки, и каждый из них имеет немного другой синтаксис, где путь должен быть задан по-разному.
Лучшее объяснение, которое я видел, - это статья из JavaWorld. Я опишу здесь, но если вы хотите узнать больше, вы должны проверить статью.
Методы
1) ClassLoader.getResourceAsStream()
.
Формат: "/" - разделенные имена; нет ведущего "/" (все имена являются абсолютными).
Пример: this.getClass().getClassLoader().getResourceAsStream("some/pkg/resource.properties");
2) Class.getResourceAsStream()
Формат: "/" - разделенные имена; ведущий "/" указывает абсолютные имена; все остальные имена относятся к пакету класса
Пример: this.getClass().getResourceAsStream("/some/pkg/resource.properties");
Ответ 4
Не используйте абсолютные пути, сделайте их относительно каталога ресурсов в вашем проекте. Быстрый и грязный код, отображающий содержимое MyTest.txt из ресурсов ресурса.
@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);
}
Ответ 5
Возможно, вы захотите попробовать это, чтобы получить поток. Сначала получите URL-адрес, а затем откройте его как поток.
URL url = getClass().getResource("/initialization/Lifepaths.txt");
InputStream strm = url.openStream();
У меня был аналогичный вопрос: Чтение txt файла из jar не выполняется, но чтение изображений работает
Ответ 6
Кажется, что проблема с ClassLoader, который вы используете. Используйте contextClassLoader для загрузки класса. Это независимо от того, находится ли он в статическом/нестационарном методе
Thread.currentThread().getContextClassLoader().getResourceAsStream
......
Ответ 7
Я оказался в подобной проблеме. Поскольку я использую maven, мне нужно было обновить pom.xml, чтобы включить что-то вроде этого:
...
</dependencies>
<build>
<resources>
<resource>
<directory>/src/main/resources</directory>
</resource>
<resource>
<directory>../src/main/resources</directory>
</resource>
</resources>
<pluginManagement>
...
Обратите внимание на тег ресурса, чтобы указать, где находится эта папка. Если у вас есть вложенные проекты (например, я), вы можете захотеть получить ресурсы из других областей, а не только в том модуле, в котором работаете. Это помогает уменьшить сохранение одного и того же файла в каждом репо, если вы используете похожие данные конфигурации
Ответ 8
Не знаю, нужна ли помощь, но в моем случае у меня был свой ресурс в папке/src/и я получал эту ошибку.
Затем я переместил изображение в папку bin и исправил проблему.
Ответ 9
Убедитесь, что ваш каталог ресурсов (например, "src" ) находится в вашем пути к классу (убедитесь, что он является исходным каталогом в пути сборки в eclipse).
Убедитесь, что clazz загружен из основного загрузчика классов.
Затем, чтобы загрузить src/initialization/Lifepaths.txt, используйте
clazz.getResourceAsStream("/initialization/Lifepaths.txt");
Почему:
clazz.getResourcesAsStream(foo)
ищет foo из класса class clazz по сравнению с классом clazz, в котором живет. Ведущий "/" заставляет его загружать из корня любой директории в classpath clazz.
Если вы не находитесь в контейнере какого-то типа, например Tomcat, или делаете что-то с ClassLoaders напрямую, вы можете просто рассматривать свой путь класса eclipse/командной строки как единственный путь класса classloader.
Ответ 10
Что сработало для меня, так это добавить файл в My Project/Java Resources/src, а затем использовать
this.getClass().getClassLoader().getResourceAsStream(myfile.txt);
Мне не нужно было объяснять добавление этого файла в путь (добавление его в /src делает это, по-видимому)
Ответ 11
В моем случае ничего не получалось, если я не удалил пробелы из имен файлов...
Ответ 12
Загрузчик классов JVM по умолчанию будет сначала использовать родительский загрузчик классов:
.
Lifepaths.class.getClass()
классов Lifepaths.class.getClass()
является bootstrap classloader
, поэтому getResourceAsStream
будет искать только $ JAVA_HOME, независимо от предоставленного пользователем classpath
. Очевидно, Lifepaths.txt не существует.
Lifepaths.class
является system classpath classloader
, поэтому getResourceAsStream
будет искать пользовательский classpath
и Lifepaths.txt там.
При использовании java.lang.Class#getResourceAsStream(String name)
, имя, которое не начинается с '/', будет добавлено с package name
качестве префикса. Если вы хотите избежать этого, пожалуйста, используйте java.lang.ClassLoader#getResourceAsStream
. Например:
ClassLoader loader = Thread.currentThread().getContextClassLoader();
String resourceName = "Lifepaths.txt";
InputStream resourceStream = loader.getResourceAsStream(resourceName);
Ответ 13
Грубо говоря:
getClass().getResource("/")
~ = Thread.currentThread().getContextClassLoader().getResource(".")
Предположим, структура вашего проекта выглядит следующим образом:
├── src
│ ├── main
│ └── test
│ └── test
│ ├── java
│ │ └── com
│ │ └── github
│ │ └── xyz
│ │ └── proj
│ │ ├── MainTest.java
│ │ └── TestBase.java
│ └── resources
│ └── abcd.txt
└── target
└── test-classes
├── com
└── abcd.txt
// in MainClass.java
this.getClass.getResource("/") -> "~/proj_dir/target/test-classes/"
this.getClass.getResource(".") -> "~/proj_dir/target/test-classes/com/github/xyz/proj/"
Thread.currentThread().getContextClassLoader().getResources(".") -> "~/proj_dir/target/test-classes/"
Thread.currentThread().getContextClassLoader().getResources("/") -> null
Ответ 14
если вы используете Maven, убедитесь, что ваша упаковка - "баночка", а не "пом".
<packaging>jar</packaging>
Ответ 15
@Emracool... Я бы предложил вам альтернативу. Так как вы пытаетесь загрузить файл *.txt. Лучше использовать FileInputStream()
, а не это раздражающее getClass().getClassLoader().getResourceAsStream()
или getClass().getResourceAsStream()
. По крайней мере, ваш код будет выполнен правильно.