Статьи

Как загрузить ресурсы из Classpath в Java с примером

Classpath в Java не только используется для загрузки файлов .class, но также может использоваться для загрузки ресурсов, например файла свойств, изображений, значков, миниатюр или любого двоичного содержимого. Java предоставляет API для чтения этих ресурсов как InputStream или URL. Предположим, у вас есть файл свойств в папке config вашего проекта, и вы хотите загрузить этот файл свойств, как вы это делаете? Точно так же у вас есть значки и эскизы для ваших веб-приложений в каталоге значков вашего проекта, как вы их загружаете? Ответ заключается в использовании метода java.lang.Class’getResource () и getResourceAsStream (). Этот метод принимает путь ресурса как String и возвращает URL и InputStream соответственно. Вы можете получить ссылку на Class, вызвав метод getClass () или используя литерал класса . Если у вас есть объект, то вы можете вызвать getClass (), потому что это нестатический метод, с другой стороны, если у вас нет объекта, вы можете просто использовать .class с именем любого класса, например Sample.class даст вам ссылку на java.lang.Class. Эти методы доступны в JDK 1.1, и вы даже можете использовать их везде, где у вас есть доступ к базовой библиотеке Java. Если вы создаете игры или приложения J2ME, вы можете использовать этот метод для загрузки значков и плиток для вашей игры, а также всех других ресурсов для вашего приложения.

Как работает getResourceAsStream

Внутренне этот метод делегирует запрос на загрузку ресурса его загрузчику классов. Если вы вызываете метод getResourceAsStream () для объекта, который загружается BootStrap ClassLoader, он делегирует его методу ClassLoader.getSystemResourceAsStream (java.lang.String). Мы передаем путь ресурса этому методу, но правила поиска ресурсов, связанных с данным классом, реализуются загрузчиком класса, определяющего класс. Поскольку вы можете передавать как абсолютный, так и относительный путь к Class.getResourceAsStream (), а ClassLoader.getResourceAsStream () принимает абсолютный путь, поэтому абсолютное имя ресурса строится из заданного имени ресурса, используя следующий алгоритм:

Если имя начинается с «/» («\ u002f»), то абсолютное имя ресурса — это часть имени, следующая за «/». В противном случае абсолютное имя имеет следующую форму:
Измененный_пакет_имя / имя, где измененный_пакет_имя — это имя пакета этого объекта с заменой ‘/’ на ‘.’ ( ‘\ u002e’).

Это означает, что имя ресурса, переданное методу, должно выглядеть как /com/abc/config/app.properties, если app.properties хранится в пакете com.abc.config вместо текущего класса.

Если вы посмотрите на код java.lang.Class в Eclipse IDE, используя сочетание клавиш Ctrl + T и введя java.lang.Class, вы увидите, как работает этот метод:

1
2
3
4
5
6
7
8
9
public InputStream getResourceAsStream(String name) {
        name = resolveName(name);
        ClassLoader cl = getClassLoader0();
        if (cl==null) {
            // A system class.
            return ClassLoader.getSystemResourceAsStream(name);
        }
        return cl.getResourceAsStream(name);
}

Этот алгоритм реализован в методе resolName (), как показано ниже:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
/**
   * Add a package name prefix if the name is not absolute Remove leading "/"
   * if name is absolute
   */
  private String resolveName(String name) {
      if (name == null) {
          return name;
      }
      if (!name.startsWith("/")) {
          Class c = this;
          while (c.isArray()) {
              c = c.getComponentType();
          }
          String baseName = c.getName();
          int index = baseName.lastIndexOf('.');
          if (index != -1) {
              name = baseName.substring(0, index).replace('.', '/')
                  +"/"+name;
          }
      } else {
          name = name.substring(1);
      }
      return name;
  }

загрузка ресурсов из classpath в Java
Основная проблема возникает при загрузке ресурса с использованием метода getResourceAsStream () — NullPointerException , поскольку этот метод возвращает значение null, если он не может найти ресурс. В следующем примере у нас есть проект Eclipse, и я создал файл свойств с именем app.properties внутри каталога конфигурации. Теперь, чтобы загрузить этот файл, мне просто нужно передать «app.properties», если я передам что-нибудь вроде «config / app.properties» или «/config/app.properties», getResourceAsStream () вернет ноль, и код впоследствии выкинет NullPointerException, как показано ниже:

1
2
3
4
5
Exception in thread "main" java.lang.NullPointerException
    at java.util.Properties$LineReader.readLine(Unknown Source)
    at java.util.Properties.load0(Unknown Source)
    at java.util.Properties.load(Unknown Source)
    at Test.main(Test.java:29)

Чтобы избежать этой ошибки, вы должны проверить вывод getResourceAsStream () перед его использованием, защитное программирование существует именно благодаря таким методам.

Java-программа для загрузки ресурсов из Classpath

Вот наша полная Java-программа для загрузки изображений, ресурсов, текстового файла или двоичного файла из classpath в Java , ресурс может быть любым, важно то, что он должен быть доступен.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
package test;
 
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.Properties;
 
/**
 * Java Program to demonstrate how to load resources e.g. properties file from
 * classpath. There are two ways to load resources in Java, one by using
 * getResourceAsStream() and getResource() method from java.lang.Class. Main
 * difference between these two methods are that one returns an InputStream
 * while other returns a URL object.
 *
 * @author Javin Paul
 */
public class ResourceLoader{
 
    public static void main(String args[]) {
 
        // loading resource using getResource() method
        InputStream in = Test.class.getResourceAsStream("app.properties");
 
        Properties config = new Properties();
        try {
            config.load(in);
            System.out.println(config.getProperty("name"));
            System.out.println(config.getProperty("version"));
 
        } catch (IOException e1) {
            e1.printStackTrace();
        }
 
        // loading resource using getResourceAsStream() method
        URL resourceURL = Test.class.getResource("app.properties");
        Properties appConfig = new Properties();
        try {
            appConfig.load(resourceURL.openStream());
            System.out.println(appConfig.getProperty("name"));
            System.out.println(appConfig.getProperty("version"));
 
        } catch (IOException e) {
            e.printStackTrace();
        }
 
    }
 
}
 
Output:
SampleApp
1.0.0
SampleApp
1.0.0

Если вы посмотрите внимательно, вы обнаружите, что мы использовали оба метода getResource () и getResourceAsStream () для загрузки ресурса из classpath в Java, в данном случае это просто файл свойств. Первый пример выглядит чище, чем второй, потому что нам не нужно открывать явный поток, метод getResourceAsStream () возвращает InputStream , который можно использовать где угодно. Это все о том, как загрузить ресурсы из class-path в Java.