Как ссылаться на файл .txt в исполняемом файле .jar [duplicate]

Вот пример:

extern const int b;

template
void f(int);

template
void f(long);

template
void g() {
    f<0, b>(0);
}
// #1

extern const int b = 0;


int main(){
    g(); 
}

// #2

Гипотетическое создание экземпляра в # 1 вызовет void f<0, b>(long), поскольку b не является постоянным выражением в этой точке, поэтому (int) перегружает SFINAE далеко. Создание экземпляра в # 2 (которое является точкой инстанцирования g) вызовет void f<0, 0>(int), потому что к тому времени b является постоянным выражением, перегрузка (int) жизнеспособна и выигрывает разрешение перегрузки.

Clang и GCC на самом деле вызывают разные f s с этим кодом.

81
задан Michael Petrotta 5 October 2010 в 09:38
поделиться

5 ответов

Разработайте решение в соответствии с тем, что вы хотите ...

Из класса, на который он вызван ...

получит две вещи, которые getResource / getResourceAsStream()
  1. Загрузитель класса
  2. Исходное местоположение

Итак, если вы сделаете

this.getClass().getResource("foo.txt");

, он попытается загрузить foo .txt из того же пакета, что и этот «класс», и с загрузчиком классов этого «класса». Если вы положили «/» спереди, вы абсолютно ссылаетесь на ресурс.

this.getClass().getResource("/x/y/z/foo.txt")

загрузит ресурс из загрузчика классов «this» и из пакета xyz (он должен быть в том же каталоге, что и классы в этом пакете).

Thread.currentThread().getContextClassLoader().getResource(name)

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

System.class.getResource(name)

Будет загружен ресурс загрузчиком системного класса (он также должен быть абсолютно привязан, так как вы не сможете поместить что-либо в пакет java.lang (пакет System).

Просто взгляните на источник. Также указывает, что getResourceAsStream просто вызывает «openStream» по URL-адресу, возвращенному из getResource, и возвращает это.

111
ответ дан mkobit 18 August 2018 в 18:33
поделиться
  • 1
    Имена пакетов AFAIK не имеют значения, это класс класса загрузчика классов. – Bart van Heukelom 5 October 2010 в 10:47
  • 2
    – Michael Wiles 5 October 2010 в 11:22
  • 3
    Ах я вижу. Абсолютный здесь означает относительный путь к классам, а не абсолютную файловую систему. – Bart van Heukelom 5 October 2010 в 12:55
  • 4
    Я просто хочу добавить, что вы всегда должны проверять, что поток, возвращаемый из getResourceAsStream (), не является нулевым, потому что это будет, если ресурс не находится в пути к классам. – stenix 22 October 2015 в 11:25
  • 5

Я ищу три места, как показано ниже. Комментарии приветствуются.

public URL getResource(String resource){

    URL url ;

    //Try with the Thread Context Loader. 
    ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
    if(classLoader != null){
        url = classLoader.getResource(resource);
        if(url != null){
            return url;
        }
    }

    //Let's now try with the classloader that loaded this class.
    classLoader = Loader.class.getClassLoader();
    if(classLoader != null){
        url = classLoader.getResource(resource);
        if(url != null){
            return url;
        }
    }

    //Last ditch attempt. Get the resource from the classpath.
    return ClassLoader.getSystemResource(resource);
}
9
ответ дан dogbane 18 August 2018 в 18:33
поделиться
  • 1
    Спасибо, это отличная идея. Только то, что мне было нужно. – devo 9 May 2012 в 18:31
  • 2
    Я смотрел комментарии в вашем коде, и последнее звучит интересно. Не все ли ресурсы загружены из класса? И в каких случаях класс ClassLoader.getSystemResource () не смог бы выполнить описанное выше? – nyxz 15 February 2015 в 13:25
  • 3
    Честно говоря, я не понимаю, почему вы хотите загружать файлы из трех разных мест. Разве вы не знаете, где хранятся ваши файлы? – bvdb 7 June 2017 в 11:46

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

Например, предположим, что SuperClass находится в A.jar и SubClass находится в B.jar, и вы выполняете код в методе экземпляра, объявленном в SuperClass, но где this ссылается на экземпляр SubClass. Если вы используете this.getClass().getResource(), он будет выглядеть относительно SubClass, в B.jar. Я подозреваю, что обычно не требуется.

Лично я бы чаще всего использовал Foo.class.getResourceAsStream(name) - если вы уже знаете имя ресурса, за которым вы находитесь, и вы «Конечно, где это относительно Foo, это самый надежный способ сделать это IMO.

Конечно, бывают случаи, когда это не , что вы хотите, тоже : судить по каждому делу по существу. Это просто «Я знаю, что этот ресурс связан с этим классом» - это самый распространенный из тех, с которыми я столкнулся.

12
ответ дан Jon Skeet 18 August 2018 в 18:33
поделиться
  • 1
    skeet: сомнение в заявлении & quot; вы выполняете код в методе экземпляра SuperClass, но где это относится к экземпляру SubClass & quot; если мы выполняем утверждения внутри метода экземпляра суперкласса, тогда «это» будет относиться к суперклассу, а не к подклассу. – Dead Programmer 5 October 2010 в 09:55
  • 2
    @Suresh: Нет, не будет. Попробуй! Создайте два класса, сделав их от другого, а затем в распечатке суперкласса this.getClass(). Создайте экземпляр подкласса и вызовите метод ... он распечатает имя подкласса, а не суперкласс. – Jon Skeet 5 October 2010 в 10:01
  • 3
    благодаря методу экземпляра подкласса вызывает метод суперкласса. – Dead Programmer 5 October 2010 в 10:15
  • 4
    Мне интересно, может ли использование this.getResourceAsStream будет иметь возможность загружать ресурс из той же банки, что и клас, а не из другой банки. По моим расчетам, это загрузчик классов, который загружает ресурс и, конечно же, не будет ограничиваться загрузкой только из одной банки? – Michael Wiles 5 October 2010 в 13:44

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

public class ResourceLoader {

    public static URL getResource(String resource) {
        final List<ClassLoader> classLoaders = new ArrayList<ClassLoader>();
        classLoaders.add(Thread.currentThread().getContextClassLoader());
        classLoaders.add(ResourceLoader.class.getClassLoader());

        for (ClassLoader classLoader : classLoaders) {
            final URL url = getResourceWith(classLoader, resource);
            if (url != null) {
                return url;
            }
        }

        final URL systemResource = ClassLoader.getSystemResource(resource);
        if (systemResource != null) {
            return systemResource;
        } else {
            try {
                return new File(resource).toURI().toURL();
            } catch (MalformedURLException e) {
                return null;
            }
        }
    }

    private static URL getResourceWith(ClassLoader classLoader, String resource) {
        if (classLoader != null) {
            return classLoader.getResource(resource);
        }
        return null;
    }

}
1
ответ дан nyxz 18 August 2018 в 18:33
поделиться

Я попробовал много способов и функций, которые были предложены выше, но они не работали в моем проекте. В любом случае я нашел решение, и вот оно:

try {
    InputStream path = this.getClass().getClassLoader().getResourceAsStream("img/left-hand.png");
    img = ImageIO.read(path);
} catch (IOException e) {
    e.printStackTrace();
}
-1
ответ дан Vladislav 18 August 2018 в 18:33
поделиться
  • 1
    В этом случае вам лучше использовать this.getClass().getResourceAsStream(). Если вы посмотрите на источник метода getResourceAsStream, вы заметите, что он делает то же самое, что и вы, но более умным способом (откат, если в классе нет ClassLoader). Это также указывает на то, что вы можете столкнуться с потенциалом null на getClassLoader в вашем коде ... – PomCompot 26 May 2017 в 07:33
  • 2
    @PromCompot, как я уже сказал, this.getClass().getResourceAsStream() не работает для меня, поэтому я использую это. Я думаю, что есть люди, которые могут столкнуться с проблемой, подобной моей. – Vladislav 27 May 2017 в 23:03
Другие вопросы по тегам:

Похожие вопросы: