2013-05-15 3 views
90

Я загружаю текстовый файл из пакета в скомпилированном JAR моего проекта Java. Соответствующая структура каталогов выглядит следующим образом:getResourceAsStream возвращает null

/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"

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

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

+3

Вы проверили, что это действительно * есть * в файле jar? Вы проверили корпус файла? –

+0

@JonSkeet Это действительно компилируется в JAR-файл в соответствующем месте, и случай правильный. – Zyerah

+0

@greedybuddha Хотя я не могу вызывать это из статического контекста, я могу вызвать его с помощью 'Lifepaths.class'. При этом, почему 'getClassLoader()' позволяет ему работать? (Также не стесняйтесь публиковать ответ!) – Zyerah

ответ

93

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

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

+42

Просто добавьте, Когда вы вызываете getResourceAsStream (имя), имя должно начинаться с «/». Я не уверен, что это необходимо, но без проблем. – David

+3

Я с этим справлялся с 8 утра этим утром. Сохранял меня. Мне также понадобилась ведущая косая черта, чтобы заставить ее работать. – kyle

+0

Я пытался в течение 2 дней найти решение моей проблемы, и, наконец, вот оно. Спасибо. –

40

Правил заключаются в следующем:

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

И попробуйте:

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

вместо

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

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

+1

Я уже сделал все эти три вещи. Пожалуйста, перечитайте мой вопрос. – Zyerah

+0

С вашего вопроса неясно, что такое «Соответствующая структура каталогов», и если вы действительно проверили, где и где находится файл в JAR (шаг 1) – Puce

+0

Ваше замечание об относительном пути, наконец, решило проблему на моем конце ; благодаря! –

26

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

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

Методы

1) ClassLoader.getResourceAsStream().

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

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

2) Class.getResourceAsStream()

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

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

+0

ваш второй пример сломан –

+1

Второй пример не сломан, как я сказал в ответе, это зависит от того, где находится ресурс. – greedybuddha

9

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

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

я когда-то был подобный вопрос: Reading txt file from jar fails but reading image works

-12

@Emracool ... Я предлагаю вам альтернативу. Так как вы пытаетесь загрузить файл * .txt. Лучше использовать FileInputStream(), а не это раздражает getClass().getClassLoader().getResourceAsStream() или getClass().getResourceAsStream(). По крайней мере, ваш код будет выполнен правильно.

+0

что ??? -1 для такого рабочего ответа. Не важно что. Но выше предлагаемое решение будет работать точно. – Jain

+0

@mu .... что вы отредактировали? – Jain

+0

отформатированы кодовые блоки. –

12

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

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

2

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

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

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

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

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

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

6

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

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

-1

То, что работало для меня, чтобы добавить файл в папке Мой проект/Java Resources/ЦСИ, а затем использовать

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

мне не нужно, чтобы добавить в явной файл в путь (добавление его/SRC делает это, по-видимому)

+0

Неверный синтаксис java –

1

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

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

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

Смежные вопросы