Java 加载与正在执行的jar文件相关的文件

Java 加载与正在执行的jar文件相关的文件,java,resources,jar,path,Java,Resources,Jar,Path,问题说明了一切 我的特殊之处在于,当前工作目录不是jar文件的位置,而是c:\Windows\system32(我的jar文件由Windows使用右键单击菜单启动,我想将文件夹的路径作为参数传递给jar) 现在我想加载一个名为config.xml的配置文件,该文件与jar位于同一文件夹中。当然,该文件的目的是为jar提供设置。为了便于编辑,xml文件在jar文件之外对我来说很重要 我很难加载那个文件。Windows执行该行 cmd /k java -jar D:\pathToJarfile\un

问题说明了一切

我的特殊之处在于,当前工作目录不是jar文件的位置,而是
c:\Windows\system32
(我的jar文件由Windows使用右键单击菜单启动,我想将文件夹的路径作为参数传递给jar)

现在我想加载一个名为
config.xml
的配置文件,该文件与jar位于同一文件夹中。当然,该文件的目的是为jar提供设置。为了便于编辑,xml文件在jar文件之外对我来说很重要

我很难加载那个文件。Windows执行该行

cmd /k java -jar D:\pathToJarfile\unpacker-0.0.1-SNAPSHOT-jar-with-dependencies.jar
使用
cmd/k
调用整个过程会使windows命令提示符保持打开状态,以便我可以看到jar的输出

由于这些函数分别返回
C:\Windows\system32\.
C:\Windows\system32
(这是Windows执行AFAIK的所有操作的工作文件夹),因此我无法对相对路径使用
new File(“.”)或
System.getProperty(“user.dir”)

我在
Launcher.class.getResourceAsStream(“/../config.xml”)
方面也没有成功。由于该路径以
/
开头,因此搜索从jar的根节点开始。转到
。/config.xml
指向该文件,但调用返回
null

有人能给我指出正确的方向吗?我真的被困在这里了。每次加载文件都让我很烦

本人要求:

  • 我不想在java源代码中硬编码路径
  • 我不想将文件路径作为参数传递给
    java-jar
    调用(既不作为
    main(String[]args)
    的参数,也不想使用
    -Dpath=d:\…
    设置系统属性)

除了最初的问题,当使用带有依赖项的
jar时,我很难让maven2将
类路径:.
放入
MANIFEST.MF
(BalusC发布的解决方案)。 问题是该行出现在普通jar的清单文件中,而不是带有dependencies.jar清单文件的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>

maven汇编插件
2.2-β-5
${mainClass}
真的
带有依赖项的jar
附属的
包裹
带有依赖项的jar
${mainClass}
.

以下是一种可能的解决方案:


以下是一种可能的解决方案,使用:


要使
Launcher.class.getResourceAsStream(“/../config.xml”)
正常工作,需要将其路径添加到JAR的
MANIFEST.MF
文件的
class path
条目中。这是正常的做法。

要使
Launcher.class.getResourceAsStream(“/../config.xml”)
正常工作,需要将其路径添加到JAR的
MANIFEST.MF
文件的
类路径
条目中。这是正常的做法。

我需要将绝对路径放入
MANIFEST.MF
还是
就足够了?后者是可取的。很抱歉,我没有尝试而是询问,我在这台机器上没有IDE。没有,是相对于JAR文件本身的路径。如果希望将
config.xml
与JAR文件本身放在同一文件夹中,那么
类路径:.
就足够了(不要忘记在
MANIFEST.MF
的末尾添加一个空行)。然后您可以通过
getResourceAsStream(“config.xml”)
获取
config.xml
。保持简单:)这是一个非常好的方法,但我无法让它工作。原因是maven汇编插件生成了带有依赖项的
jar
。在常规的.jar文件中,我的
MANIFEST.MF
被正确地放入jar中,但是带有依赖项的
jar文件没有使用我指定的MANIFEST:-/有人知道这个问题的快速解决方案吗?对不起,我没有使用Maven,所以我无法详细说明。您至少应该在某个地方指定要包含在类路径中的额外依赖路径。顺便说一句,如果
启动器
类本身在另一个包中,您应该使用
“/config.xml”
作为资源名称,这是对前面注释的更正。否则它看起来是相对于
Launcher
类(在JAR中)的位置的。我现在可以使用
InputStream fromFile=Launcher.class.getResourceAsStream(“/config.xml”)很好的答案,谢谢!我是否需要将绝对路径放入
MANIFEST.MF
就足够了?后者是可取的。很抱歉,我没有尝试而是询问,我在这台机器上没有IDE。没有,是相对于JAR文件本身的路径。如果希望将
config.xml
与JAR文件本身放在同一文件夹中,那么
类路径:.
就足够了(不要忘记在
MANIFEST.MF
的末尾添加一个空行)。然后您可以通过
getResourceAsStream(“config.xml”)
获取
config.xml
。保持简单:)这是一个非常好的方法,但我无法让它工作。原因是maven汇编插件生成了带有依赖项的
jar
。在常规的.jar文件中,我的
MANIFEST.MF
被正确地放入jar中,但是带有依赖项的
jar文件没有使用我指定的MANIFEST:-/有人知道这个问题的快速解决方案吗?对不起,我没有使用Maven,所以我无法详细说明。您至少应该在某个地方指定要包含在类路径中的额外依赖路径。顺便说一句
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.
}
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.