Как правильно ссылаться на файл ресурсов для JAR и отладки?
У меня есть неприятная проблема с ссылкой на ресурсы при использовании проекта Maven и файлов Jar...
У меня есть все мои ресурсы в выделенной папке /src/main/resources, которая является частью пути сборки в Eclipse. Файлы ссылаются с помощью
getClass().getResource("/filename.txt")
Это отлично работает в Eclipse, но не работает в Jar файле - там ресурсы находятся в папке непосредственно под корнем jar...
Кто-нибудь знает "лучшую практику" для ссылки на файл как в JAR, так и (!) в Eclipse?
Edit:
Проблема в том, что, хотя ресурсы на самом деле находятся в JAR в папке "ресурсы" на верхнем уровне, вышеупомянутый метод не может найти файл...
Ответы
Ответ 1
Содержимое папок ресурсов Maven копируется в целевые/классы и оттуда в корень результирующего файла Jar. Это ожидаемое поведение.
Я не понимаю, что проблема в вашем сценарии. Ссылка на ресурс через getClass().getResource("/filename.txt")
начинается с корня пути к классу, независимо от того, является ли это (или его элемент) target/classes
или корнем JAR. Единственная возможная ошибка, которую я вижу, заключается в том, что вы используете неправильный ClassLoader
.
Убедитесь, что класс, который использует ресурс, находится в одном и том же артефакте (JAR) в качестве ресурса и делает ThatClass.class.getResource("/path/with/slash")
или ThatClass.class.getClassLoader().getResource("path/without/slash")
.
Но кроме этого: если он не работает, вы, вероятно, что-то делаете неправильно в процессе сборки. Вы можете проверить, что ресурс находится в JAR?
Ответ 2
У меня была аналогичная проблема.
После полного дня попытки каждой комбинации и отладки я попробовал getClass(). GetResourceAsStream ( "resources/filename.txt" ) и заставил его работать наконец.
Больше ничего не помогло.
Ответ 3
Как только вы упакуете JAR, ваши файлы ресурсов больше не являются файлами, а потоком, поэтому getResource
не будет работать!
Используйте getResourceAsStream
.
Чтобы получить содержимое "файла", используйте https://commons.apache.org/proper/commons-io/javadocs/api-release/org/apache/commons/io/IOUtils.html:
static public String getFile(String fileName)
{
//Get file from resources folder
ClassLoader classLoader = (new A_CLASS()).getClass().getClassLoader();
InputStream stream = classLoader.getResourceAsStream(fileName);
try
{
if (stream == null)
{
throw new Exception("Cannot find file " + fileName);
}
return IOUtils.toString(stream);
}
catch (Exception e) {
e.printStackTrace();
System.exit(1);
}
return null;
}
Ответ 4
Проблема заключается в том, что в среде IDE getClass(). getResource ( "Путь" ); Строка не является CASE SENSITIVE при доступе к файлу, но при запуске из банки. Проверьте свою капитализацию по каталогу по сравнению с файлом. Он работает. Также, если вы попробуете новый файл (getClass(). GetResource ( "Путь" ), файл не будет доступен для чтения вне IDE.
Ответ 5
Может быть, этот метод может помочь в некоторых ситуациях.
public static File getResourceFile(String relativePath)
{
File file = null;
URL location = <Class>.class.getProtectionDomain().getCodeSource().getLocation();
String codeLoaction = location.toString();
try{
if (codeLocation.endsWith(".jar"){
//Call from jar
Path path = Paths.get(location.toURI()).resolve("../classes/" + relativePath).normalize();
file = path.toFile();
}else{
//Call from IDE
file = new File(<Class>.class.getClassLoader().getResource(relativePath).getPath());
}
}catch(URISyntaxException ex){
ex.printStackTrace();
}
return file;
}
Ответ 6
Если вы добавляете каталог ресурсов в файл jar (поэтому он находится в папке /resources в банке, и если /src/main находится в вашем пути сборки в eclipse, вы должны иметь возможность ссылаться на ваш файл как
getClass().getResource("/resources/filename.txt");
Что должно работать в обеих средах.
Ответ 7
Просто скопируйте файл во временный каталог.
String tempDir = System.getProperty("java.io.tmpdir");
File file = new File(tempDir.getAbsolutePath(), "filename.txt");
if (!file.exists()) {
InputStream is = (getClass().getResourceAsStream("/filename.txt"));
Files.copy(is, file.getAbsoluteFile().toPath());
}