Загрузка файла относительно исполняемого файла JAR - PullRequest
13 голосов
/ 02 сентября 2010

Вопрос говорит сам за себя.

Специальность в моем случае заключается в том, что текущим рабочим каталогом является не местоположение файла JAR, а c:\Windows\system32 (Мой файл JAR запускается окнами с использованием правогощелкните меню, я хочу передать путь к папке в качестве параметра к банке).

Теперь я хочу загрузить файл конфигурации с именем config.xml, который находится в той же папке, что и банка.Назначение файла, конечно, предоставить настройки для фляги.Для меня важно, чтобы xml-файл находился вне файла jar для легкого редактирования.

У меня проблемы с загрузкой этого файла.Windows выполняет строку

cmd /k java -jar D:\pathToJarfile\unpacker-0.0.1-SNAPSHOT-jar-with-dependencies.jar

Вызов всего этого с помощью cmd /k оставляет командную строку Windows открытой, чтобы я мог видеть выходные данные jar.

Я не могу использовать new File(".") или System.getProperty("user.dir") для относительного пути, поскольку эти функции возвращают C:\Windows\system32\. и C:\Windows\system32 соответственно (это рабочая папка для всего, что windows выполняет AFAIK).

У меня не было успеха и с Launcher.class.getResourceAsStream("/../config.xml"),Поскольку этот путь начинается с /, поиск начинается с корневого узла фляги.Переход к ../config.xml указывает точно на этот файл, но вызов возвращает null.

Может ли кто-нибудь указать мне правильное направление?Я действительно застрял здесь.Эти вещи при загрузке файлов действительно доставляют мне неприятности каждый раз ...

Требования к себе:

  • Я не хочу жестко задавать путь в исходном коде Java
  • Я не хочу передавать путь к файлу в качестве параметра в вызов java -jar (ни в качестве параметра main(String[] args), ни с помощью -Dpath=d:\... для установки системного свойства)

В дополнение к исходной проблеме, мне было трудно заставить maven2 поместить Class-Path: . в MANIFEST.MF (решение, опубликованное BalusC) при использовании jar-with-dependencies.Проблема заключалась в том, что строка появилась в файле MANIFEST обычного jar, а не в файле MANIFEST jar-with-dependencies.jar (генерируется 2 файла jar).Для тех, кому все равно, как я это сделал:

<plugin>
    <artifactId>maven-assembly-plugin</artifactId>
    <version>2.2-beta-5</version>
    <configuration>
      <archive>
        <manifest>
          <mainClass>${mainClass}</mainClass>
          <addClasspath>true</addClasspath>
          <!--at first, i tried to place the Class-Path entry
              right here using <manifestEntries>. see below -->
        </manifest>
      </archive>
      <descriptorRefs>
        <descriptorRef>jar-with-dependencies</descriptorRef>
      </descriptorRefs>
    </configuration>
    <executions>
      <execution>
        <goals>
          <goal>attached</goal>
        </goals>
        <phase>package</phase>
        <configuration>
          <descriptorRefs>
            <descriptorRef>jar-with-dependencies</descriptorRef>
          </descriptorRefs>
          <archive>
            <manifest>
              <mainClass>${mainClass}</mainClass>
            </manifest>
            <!--this is the correct placement -->
            <manifestEntries>
              <Class-Path>.</Class-Path>
            </manifestEntries>
          </archive>
        </configuration>
      </execution>
    </executions>
  </plugin>

Ответы [ 2 ]

12 голосов
/ 02 сентября 2010

Вот одно из возможных решений с использованием Class.getProtectionDomain () :

final Class<?> referenceClass = YourMainClass.class;
final URL url =
    referenceClass.getProtectionDomain().getCodeSource().getLocation();

try{
    final File jarPath = new File(url.toURI()).getParentFile();
    System.out.println(jarPath); // this is the path you want 
} catch(final URISyntaxException e){
    // etc.
}

YourMainClass можно заменить любым классом в вашей банке.


Из Class.getProtectionDomain () документы:

Returns the ProtectionDomain of this class.
If there is a security manager installed, this method first calls
the security manager's checkPermission method with a
RuntimePermission("getProtectionDomain") permission to ensure it's
ok to get the ProtectionDomain.

Returns:
  the ProtectionDomain of this class
Throws:
  SecurityException - if a security manager exists and its
  checkPermission method doesn't allow getting the ProtectionDomain.
6 голосов
/ 02 сентября 2010

Чтобы заставить Launcher.class.getResourceAsStream("/../config.xml") работать, вам необходимо добавить его путь к записи Class-Path файла JAR MANIFEST.MF.Это нормальная практика.

...