Загрузка файла относительно исполняемого файла JAR
Вопрос говорит обо всем.
В моем случае особенность заключается в том, что текущим рабочим каталогом является не местоположение файла JAR, а c:\Windows\system32
(Мой файл jar запускается окнами с помощью меню, вызываемого правой кнопкой мыши, я хочу передать путь к папке в качестве параметра jar).
Теперь я хочу загрузить файл конфигурации с именем config.xml
это находится в той же папке, что и банка. Назначение файла, конечно, предоставить настройки для фляги. Для меня важно, чтобы xml-файл находился вне jar-файла для удобного редактирования.
Мне тяжело загружать этот файл. Windows выполняет строку
cmd /k java -jar D:\pathToJarfile\unpacker-0.0.1-SNAPSHOT-jar-with-dependencies.jar
Называя все это с cmd /k
оставляет командную строку windows открытой, чтобы я мог видеть вывод банки.
Я не могу использовать 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 ответа
Получить Launcher.class.getResourceAsStream("/../config.xml")
чтобы работать, нужно добавить свой путь к Class-Path
вход в банки MANIFEST.MF
файл. Это нормальная практика.
Вот одно из возможных решений с использованием 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.