Java 加载相对于正在执行的 jar 文件的文件
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3627426/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Loading a file relative to the executing jar file
提问by f1sh
The question says it all.
问题说明了一切。
The specialty in my case is that the current working directory is not the location of the jar file but c:\Windows\system32
(My jar file is started by windows using the right-click-menu, i want to pass a folder's path as a parameter to the jar).
我的情况的特点是当前工作目录不是 jar 文件的位置,而是c:\Windows\system32
(我的 jar 文件是由 windows 使用右键单击菜单启动的,我想将文件夹的路径作为参数传递给 jar) .
Now I want to load a configuration file called config.xml
that is in the same folder as the jar. The purpose of the file is, of course, to provide settings for the jar. It is important for me that the xml file is outsideof the jar file for easy editing.
现在我想加载一个config.xml
与 jar 位于同一文件夹中的配置文件。该文件的目的当然是为 jar 提供设置。xml 文件位于jar 文件之外以便于编辑对我来说很重要。
I'm having a hard time loading that file. Windows executes the line
我很难加载那个文件。Windows 执行该行
cmd /k java -jar D:\pathToJarfile\unpacker-0.0.1-SNAPSHOT-jar-with-dependencies.jar
Calling the whole thing with cmd /k
leaves the windows command prompt open so that I can see the jar's output.
调用整个过程会cmd /k
打开 Windows 命令提示符,以便我可以看到 jar 的输出。
I cannot use new File(".")
or System.getProperty("user.dir")
for the relative path as these functions return C:\Windows\system32\.
and C:\Windows\system32
, respectively (which is the working folder for everything that windows executes AFAIK).
我不能使用new File(".")
或System.getProperty("user.dir")
作为相对路径,因为这些函数分别返回C:\Windows\system32\.
和C:\Windows\system32
(这是Windows 执行AFAIK 的所有内容的工作文件夹)。
I've had no success with Launcher.class.getResourceAsStream("/../config.xml")
either. Since that path begins with /
, searching starts at the root node of the jar. Going to ../config.xml
point exactly to that file, but the call returns null
.
我也没有成功Launcher.class.getResourceAsStream("/../config.xml")
。由于该路径以 开头/
,因此搜索从 jar 的根节点开始。将../config.xml
精确指向该文件,但调用返回null
.
Can someone point me in the right direction? I'm really stuck here. This file loading stuff really bugs me everytime...
有人可以指出我正确的方向吗?我真的被困在这里了。这个文件加载的东西每次都让我很烦恼......
Requirements by myself:
本人要求:
- I don't want to hardcode the path in the java source code
- I don't want to pass the file's path as a parameter to the
java -jar
call (neither as a param to themain(String[] args)
nor using-Dpath=d:\...
to set a system property)
- 我不想在 java 源代码中硬编码路径
- 我不想将文件的路径作为参数传递给
java -jar
调用(既不是作为参数main(String[] args)
也不是-Dpath=d:\...
用于设置系统属性)
In addition to the original problem, I had a hard time to have maven2 place Class-Path: .
into the MANIFEST.MF
(The solution that BalusC posted) when using jar-with-dependencies
.
The problem was that the line appeared in the regular jar's MANIFEST file, but not the jar-with-dependencies.jar's MANIFEST file (2 jar files are generated).
For anyone who cares how i did it:
除了原来的问题,我有一个很难有maven2的地方Class-Path: .
入MANIFEST.MF
(即BalusC发布的解决方案)使用时jar-with-dependencies
。问题是该行出现在常规 jar 的 MANIFEST 文件中,但没有出现在 jar-with-dependencies.jar 的 MANIFEST 文件中(生成了 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>
采纳答案by BalusC
To get Launcher.class.getResourceAsStream("/../config.xml")
to work, you need to add its path to the Class-Path
entry of the JAR's MANIFEST.MF
file. This is the normal practice.
要开始Launcher.class.getResourceAsStream("/../config.xml")
工作,您需要将其路径添加到Class-Path
JARMANIFEST.MF
文件的条目中。这是正常的做法。
回答by Sean Patrick Floyd
Here is one possible solution using Class.getProtectionDomain():
这是使用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
can be replaced by any class in your jar.
YourMainClass
可以替换为 jar 中的任何类。
From the Class.getProtectionDomain()docs:
来自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.