Как загрузить папку из .jar? - PullRequest
6 голосов
/ 06 июня 2011

OK.Поэтому у меня довольно простой вопрос: я хочу иметь возможность загружать ресурс (целую папку) из запущенного файла .jar, но я не смог заставить его работать.Это то, что я пробовал (если имя класса было «myClass» и папка называлась «myFolder»), но всегда выдает исключение NullPointerException:

URL folderURL = myClass.class.getClassLoader().getResource("myFolder/");
String folderPath = folderURL.getPath();
File myFolder = new File(folderPath);

Исключение NullPointerException всегда выдается перед созданием »моя папка".

Дополнительная информация: мне нужно получить доступ к папке из статического контекста.Класс, который обращается к папке, НЕ находится в том же каталоге, в котором находится сама папка. (Папка находится в корневом каталоге внутри jar, класс - это пара подпакетов вниз.)

Есть ли у кого-нибудьрешение моей проблемы?Извините, если я использовал неправильную терминологию: P, но все, что вы можете сделать, чтобы помочь, приветствуется.

Ответы [ 4 ]

21 голосов
/ 06 июня 2011

Нет, это не сработает.Вы пытаетесь создать объект File из ресурса внутри JAR.Этого не произойдет.Лучший способ загрузки ресурсов - сделать одну из папок вашего пакета папкой ресурсов, затем создать в ней файл Resources.jar или что-то в этом роде, выгрузить ваши ресурсы в тот же каталог и затем использовать Resources.class.getResourceAsStream(resFileName) в других ваших файлах классов Java.

Если вам нужно «перебрать» подфайлы в каталоге JAR, на которые указывает URL-адрес, заданный getResource(..), используйте следующее (хотя это немного хак!).Он будет работать и для обычной файловой системы:

  /**
   * List directory contents for a resource folder. Not recursive.
   * This is basically a brute-force implementation.
   * Works for regular files and also JARs.
   * 
   * @author Greg Briggs
   * @param clazz Any java class that lives in the same place as the resources you want.
   * @param path Should end with "/", but not start with one.
   * @return Just the name of each member item, not the full paths.
   * @throws URISyntaxException 
   * @throws IOException 
   */
  String[] getResourceListing(Class clazz, String path) throws URISyntaxException, IOException {
      URL dirURL = clazz.getClassLoader().getResource(path);
      if (dirURL != null && dirURL.getProtocol().equals("file")) {
        /* A file path: easy enough */
        return new File(dirURL.toURI()).list();
      } 

      if (dirURL == null) {
        /* 
         * In case of a jar file, we can't actually find a directory.
         * Have to assume the same jar as clazz.
         */
        String me = clazz.getName().replace(".", "/")+".class";
        dirURL = clazz.getClassLoader().getResource(me);
      }

      if (dirURL.getProtocol().equals("jar")) {
        /* A JAR path */
        String jarPath = dirURL.getPath().substring(5, dirURL.getPath().indexOf("!")); //strip out only the JAR file
        JarFile jar = new JarFile(URLDecoder.decode(jarPath, "UTF-8"));
        Enumeration<JarEntry> entries = jar.entries(); //gives ALL entries in jar
        Set<String> result = new HashSet<String>(); //avoid duplicates in case it is a subdirectory
        while(entries.hasMoreElements()) {
          String name = entries.nextElement().getName();
          if (name.startsWith(path)) { //filter according to the path
            String entry = name.substring(path.length());
            int checkSubdir = entry.indexOf("/");
            if (checkSubdir >= 0) {
              // if it is a subdirectory, we just return the directory name
              entry = entry.substring(0, checkSubdir);
            }
            result.add(entry);
          }
        }
        return result.toArray(new String[result.size()]);
      } 

      throw new UnsupportedOperationException("Cannot list files for URL "+dirURL);
  }

Затем вы можете изменить URL-адрес, заданный getResource(..), добавить файл в конец и передать эти URL-адреса в getResourceAsStream(..), готовый к загрузке.Если вы этого не поняли, вам нужно прочитать о загрузке классов.

1 голос
/ 06 июня 2011

Все довольно просто:

getClass().getResourceAsStream("/resources/images/myImage.png")

Возвращает входной поток, который можно использовать так:

Image myImage = ImageIO.read(getClass().getResourceAsStream("/resources/images/myImage.png"));

И оттуда, используйте свой образ, как вам нравится. Это также работает так же хорошо, если вы используете поток ввода для чтения текстового файла, или почти для всего, что вы делаете.

Edit: Путь выше относится к корню .jar.

0 голосов
/ 20 декабря 2017

До сих пор (декабрь 2017 года) это единственное решение, которое я нашел и которое работает как внутри и снаружи IDE (с использованием PathMatchingResourcePatternResolver ): https://stackoverflow.com/a/47904173/6792588

0 голосов
/ 18 августа 2014

Я думаю, что я на что-то.В Eclipse создайте новую исходную папку с именем «resources» и в этой папке создайте пакет с именем «myFolder».Чтобы иметь путь к «myFolder», вам просто нужно сказать:

Path path = Paths.get(Main.class.getResource("/myFolder").toURI()); // or the class name instead of Main
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...