Вопрос-ответ

Reading a resource file from within jar

Чтение файла ресурсов из jar

Я хотел бы прочитать ресурс из моего jar следующим образом:

File file;
file = new File(getClass().getResource("/file.txt").toURI());
BufferedReader reader = new BufferedReader(new FileReader(file));

//Read the file

и он отлично работает при запуске в Eclipse, но если я экспортирую его в jar, а затем запускаю, возникает исключение IllegalArgumentException:

Exception in thread "Thread-2"
java.lang.IllegalArgumentException: URI is not hierarchical

и я действительно не знаю почему, но после некоторого тестирования я обнаружил, что если я изменю

file = new File(getClass().getResource("/file.txt").toURI());

Для

file = new File(getClass().getResource("/folder/file.txt").toURI());

тогда все работает наоборот (это работает в jar, но не в eclipse).

Я использую Eclipse, и папка с моим файлом находится в папке класса.

Переведено автоматически
Ответ 1

Вместо того, чтобы пытаться обращаться к ресурсу как к файлу, просто попросите ClassLoader вместо этого вернуть InputStream для ресурса через getResourceAsStream:

try (InputStream in = getClass().getResourceAsStream("/file.txt");
BufferedReader reader = new BufferedReader(new InputStreamReader(in))) {
// Use resource
}

Пока file.txt ресурс доступен по пути к классу, этот подход будет работать одинаково, независимо от того, находится ли file.txt ресурс в classes/ каталоге или внутри jar.

Это URI is not hierarchical происходит потому, что URI для ресурса в файле jar будет выглядеть примерно так: file:/example.jar!/file.txt. Вы не можете читать записи внутри jar (zip файла), как будто это был обычный старый файл.

Это хорошо объясняется ответами на:

Ответ 2

Чтобы получить доступ к файлу в jar, у вас есть два варианта:


  • Поместите файл в структуру каталогов, соответствующую имени вашего пакета (после извлечения файла .jar он должен находиться в том же каталоге, что и файл .class), затем получите к нему доступ с помощью getClass().getResourceAsStream("file.txt")


  • Поместите файл в корневой каталог (после извлечения файла .jar он должен быть в корневом каталоге), затем получите к нему доступ с помощью Thread.currentThread().getContextClassLoader().getResourceAsStream("file.txt")


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

Ответ 3

I had this problem before and I made fallback way for loading. Basically first way work within .jar file and second way works within eclipse or other IDE.

public class MyClass {

public static InputStream accessFile() {
String resource = "my-file-located-in-resources.txt";

// this is the path within the jar file
InputStream input = MyClass.class.getResourceAsStream("/resources/" + resource);
if (input == null) {
// this is how we load file within editor (eg eclipse)
input = MyClass.class.getClassLoader().getResourceAsStream(resource);
}

return input;
}
}
Ответ 4

Up until now (December 2017), this is the only solution I found which works both inside and outside the IDE.

Use PathMatchingResourcePatternResolver

Note: it works also in spring-boot

In this example I'm reading some files located in src/main/resources/my_folder:

try {
// Get all the files under this inner resource folder: my_folder
String scannedPackage = "my_folder/*";
PathMatchingResourcePatternResolver scanner = new PathMatchingResourcePatternResolver();
Resource[] resources = scanner.getResources(scannedPackage);

if (resources == null || resources.length == 0)
log.warn("Warning: could not find any resources in this scanned package: " + scannedPackage);
else {
for (Resource resource : resources) {
log.info(resource.getFilename());
// Read the file content (I used BufferedReader, but there are other solutions for that):
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(resource.getInputStream()));
String line = null;
while ((line = bufferedReader.readLine()) != null) {
// ...
// ...
}
bufferedReader.close();
}
}
} catch (Exception e) {
throw new Exception("Failed to read the resources folder: " + e.getMessage(), e);
}
java file jar