it-roy-ru.com

getResourceAsStream возвращает ноль

Я загружаю текстовый файл из пакета в скомпилированный 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"

Ни одна из этих работ. Ячитаюмногочисленныевопросы до сих пор по теме, но ни один из них не помог - обычно, они просто говорят, чтобы загрузить файлы, используя корневой путь, который Я уже делаю. Это, или просто загрузите файл из текущего каталога (просто загрузите filename), что я тоже попробовал. Файл компилируется в JAR в соответствующем месте с соответствующим именем. 

Как мне это решить?

135
Zyerah

Lifepaths.class.getClass().getResourceAsStream(...) загружает ресурсы с помощью системного загрузчика классов, очевидно, что происходит сбой, потому что он не видит ваши JAR-файлы

Lifepaths.class.getResourceAsStream(...) загружает ресурсы, используя тот же загрузчик классов, что и класс Lifepaths, и он должен иметь доступ к ресурсам в ваших JAR-файлах.

125
hoaz

Правила следующие:

  1. проверьте расположение файла, который вы хотите загрузить внутри JAR (и, таким образом, также убедитесь, что он действительно добавлен в JAR)
  2. используйте либо абсолютный путь: путь начинается с корня JAR
  3. использовать относительный путь: путь начинается в каталоге пакета класса, который вы вызываете getResource/getResoucreAsStream

И попробовать:

Lifepaths.class.getResourceAsStream("/initialization/Lifepaths.txt")

вместо

Lifepaths.class.getClass().getResourceAsStream("/initialization/Lifepaths.txt")

(не уверен, если это имеет значение, но первый будет использовать правильный ClassLoader/JAR, хотя я не уверен с последним)

50
Puce

Таким образом, есть несколько способов получить ресурс из jar-файла, и каждый из них имеет немного другой синтаксис, где путь должен быть указан по-разному.

Лучшее объяснение, которое я видел, - это статья из JavaWorld . Я подведу итоги здесь, но если вы хотите узнать больше, вы должны проверить статью.

Методы

1) ClassLoader.getResourceAsStream()

Формат: "/" - разделенные имена; без начального "/" (все имена являются абсолютными). 

Пример: this.getClass().getClassLoader().getResourceAsStream("some/pkg/resource.properties");

2) Class.getResourceAsStream()

Формат: "/" - разделенные имена; ведущий "/" обозначает абсолютные имена; все остальные имена относятся к пакету класса

Пример: this.getClass().getResourceAsStream("/some/pkg/resource.properties");

40
greedybuddha

Не используйте абсолютные пути, делайте их относительно каталога ресурсов в вашем проекте. Быстрый и грязный код, который отображает содержимое 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);
}
12
Paul Smith

Возможно, вы захотите попробовать это, чтобы получить поток, т.е. сначала получите URL, а затем откройте его как поток. 

URL url = getClass().getResource("/initialization/Lifepaths.txt"); 
InputStream strm = url.openStream(); 

У меня когда-то был похожий вопрос: Считать txt файл из jar не удается, но чтение изображения работает

9
MrD

Кажется, есть проблема с ClassLoader, который вы используете. Используйте contextClassLoader для загрузки класса. Это независимо от того, находится ли он в статическом/нестатическом методе

Thread.currentThread().getContextClassLoader().getResourceAsStream......

6
Binita Bharati

Не знаю, поможет ли это, но в моем случае мой ресурс находился в папке/src /, и я получал эту ошибку .... Затем я переместил изображение в папку bin, и это устранило проблему.

2
Leo Ufimtsev

Убедитесь, что ваш каталог ресурсов (например, "src") находится в вашем classpath (убедитесь, что это каталог с исходным кодом в вашем пути сборки в Eclipse).

Убедитесь, что clazz загружен из основного загрузчика классов.

Затем, чтобы загрузить src/initialization/Lifepaths.txt, используйте 

clazz.getResourceAsStream("/initialization/Lifepaths.txt");

Почему: clazz.getResourcesAsStream(foo) ищет foo из в пределах пути к классам clazz , относительно каталога, в котором живет clazz . Начальный символ "/" загружает его из корня любого каталога в classpath clazz.

Если вы не находитесь в каком-либо контейнере, таком как Tomcat, или не делаете что-то непосредственно с ClassLoaders, вы можете просто трактовать свой путь к классу Eclipse/командной строки как единственный путь к классу загрузчика классов.

2
Bobby Martin

Я оказался в похожей проблеме. Так как я использую maven, мне нужно было обновить мой pom.xml, чтобы включить что-то вроде этого:

   ...
</dependencies>
<build>
    <resources>
        <resource>
            <directory>/src/main/resources</directory>
        </resource>
        <resource>
            <directory>../src/main/resources</directory>
        </resource>
    </resources>
    <pluginManagement>
        ...

Обратите внимание на тег ресурса, чтобы указать, где находится эта папка. Если у вас есть вложенные проекты (как у меня), то вы можете получить ресурсы из других областей, а не только из модуля, в котором вы работаете. Это помогает уменьшить хранение одного и того же файла в каждом репо, если вы используете аналогичные данные конфигурации 

1
plosco

В моем случае ничего не получалось, если я не удалил пробелы из имен файлов ...

0
user3563159

Для меня работало, чтобы добавить файл в мой проект/Java Resources/src, а затем использовать 

this.getClass().getClassLoader().getResourceAsStream(myfile.txt);

Мне не нужно было подробно добавлять этот файл к пути (очевидно, добавление его в/src)

0
Pablo