Как правильно ссылаться на файл ресурса для JAR и отладки? - PullRequest
41 голосов
/ 31 мая 2011

У меня неприятная проблема со ссылками на ресурсы при использовании проекта Maven и файлов Jar ...

Все мои ресурсы находятся в отдельной папке / src / main / resources, которая является частью пути сборки в Eclipse. На файлы ссылаются, используя

getClass().getResource("/filename.txt")

Это отлично работает в Eclipse, но не работает в файле Jar - там ресурсы расположены в папке, прямо под корнем jar ...

Кто-нибудь знает «лучшую практику» для ссылки на файл как в JAR, так и (!) В Eclipse?

Edit: Проблема в том, что, хотя ресурсы фактически находятся в JAR в папке «resources» на верхнем уровне, вышеуказанный метод не может найти файл ...

Ответы [ 7 ]

18 голосов
/ 12 сентября 2013

У меня была похожая проблема. После полного дня попытки каждой комбинации и отладки я попробовал getClass (). GetResourceAsStream ("resources / filename.txt") и заставил его наконец работать. Больше ничего не помогло.

18 голосов
/ 31 мая 2011

Содержимое папок ресурсов Maven копируется в target / классы и оттуда в корень результирующего файла Jar. Это ожидаемое поведение.

Я не понимаю, в чем проблема в вашем сценарии. Ссылка на ресурс через getClass().getResource("/filename.txt") начинается с корня пути к классу, независимо от того, является ли он (или его элемент) target/classes или корнем JAR. Единственная возможная ошибка, которую я вижу, это то, что вы используете неправильный ClassLoader.

Убедитесь, что класс, использующий ресурс, находится в том же артефакте (JAR), что и ресурс, и выполните ThatClass.class.getResource("/path/with/slash") или ThatClass.class.getClassLoader().getResource("path/without/slash").

Но кроме этого: если это не работает, вы, вероятно, делаете что-то не так в процессе сборки. Можете ли вы проверить, что ресурс находится в JAR?

17 голосов
/ 03 мая 2017

После того, как вы упакуете 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;
}
0 голосов
/ 11 января 2019

Может быть, этот метод может помочь в некоторых ситуациях.

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;
}
0 голосов
/ 30 сентября 2017

Проблема в том, что в среде IDE getClass (). GetResource ("Path");Строка не является CASE SENSITIVE при доступе к файлу, но при запуске из jar-файла это так.Проверьте вашу заглавную букву в каталоге по сравнению с файлом.Это работает.Также, если вы попробуете новый File (getClass (). GetResource ("Path"), файл не будет доступен для чтения вне IDE.

0 голосов
/ 14 ноября 2013

Просто скопируйте файл во временный каталог.

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());
}
0 голосов
/ 31 мая 2011

Если вы добавите каталог ресурсов в файл jar (таким образом, он находится в папке / resources в jar, и если / src / main находится в вашем пути сборки в eclipse, тогда вы сможете ссылаться на ваш файл как:

getClass().getResource("/resources/filename.txt");  

, который должен работать в обеих средах.

...