【问题标题】:Getting the path of a running JAR file returns "rsrc:./"获取正在运行的 JAR 文件的路径返回“rsrc:./”
【发布时间】:2016-10-20 12:57:14
【问题描述】:

我的代码在 JAR 文件中运行,我需要获取该文件的完整路径。 例如,我的 JAR 名为 example.jar,位于 D:\example\ 所以我需要通过该 jar 中的一些代码获取“D:\example\example.jar”。 我已经尝试了很多方法来获得该路径,但没有一个能正常工作。

其中一个是

getClass().getProtectionDomain().getCodeSource().getLocation().toURI().getPath()

很多人说这对他们有用,但它为我返回“rsrc:./”。

之后我进行了搜索,发现我的 MANIFEST.MF 包含以下内容:

Manifest-Version: 1.0
Rsrc-Class-Path: ./
Class-Path: .
Rsrc-Main-Class: Example
Main-Class: org.eclipse.jdt.internal.jarinjarloader.JarRsrcLoader

我不知道那是什么意思,但是如果我删除那个 Rsrc 的东西并用它替换其他的东西,它就会说 jar 坏了。我认为这就是它不起作用的原因。有人知道这是什么意思吗?

PS:我正在使用 BAT 文件运行我的 JAR。

【问题讨论】:

  • 为什么要获取JAR的路径?
  • getPath() 将 URI 转换为文件。即使它是一个文件:URI,路径部分也可能包含百分比转义,因此使用 getPath() 最终将返回一个不是有效文件名的字符串。将 URI 转换为文件名的正确方法是 Paths.get(uri),但它仅适用于 file: URI。也就是说,无论您尝试做什么,都可以并且应该使用 Class.getResource 或 ClassLoader.getResource 来完成。
  • 你可以得到jar本身的路径,但是谈论jar中文件的文件路径是没有意义的。
  • @SJuan76 我想将 JAR 中的一些文件和文件夹复制到 JARs 目录中。如果我只输入“D:\example\example.jar”就可以了,但路径并不总是相同的。
  • @VGR 我如何使用 Class(Loader).getResource() 找出 JAR 路径?

标签: java jar path manifest rsrc


【解决方案1】:

我也偶然发现了这个问题,并将我的调查留给将来问自己rsrc 是什么意思的人。

我正在使用 Eclipse Mars 1 并尝试将我的项目导出为可运行的 JAR。在那里我可以选择库处理并做出决定:

  1. 将所需的库提取到生成的 JAR 中
  2. 将所需的库打包到生成的 JAR 中
  3. 将所需的库复制到生成的 JAR 旁边的子文件夹中

要测试的行是

System.out.println(MyClass.class.getProtectionDomain().getCodeSource().getLocation());

JAR 文件的名称是 MyJar.jar(将放在桌面上),项目的名称和文件夹是 MyProject。

结果:

  1. file:/C:/Users/admin/Desktop/MyJar.jar
  2. rsrc:./
  3. file:/C:/Users/admin/Desktop/MyJar.jar
  4. file:/C:/Development/workspace/MyProject/target/classes/

我为此写了一个方便的方法:

public class SystemUtils {

    /**
     * Let no one instanciate this class.
     */
    private SystemUtils() {}

    /**
     * If the current JVM was started from within a JAR file. 
     * @return <code>Boolean.TRUE</code> if it is, <code>Boolean.FALSE</code> if it is not, <code>null</code> if unknown.
     */
    public static Boolean executedFromWithinJar() {
        Boolean withinJar = null;
        try {
            String location = SystemUtils.class.getProtectionDomain().getCodeSource().getLocation().toString();
            if (location.startsWith("rsrc:")
                || location.endsWith(".jar") && !new File(location.substring(location.indexOf(':') + 1)).isDirectory())
                withinJar = Boolean.TRUE;
            else
                withinJar = Boolean.FALSE;
        }
        catch (Exception ex) {/* value is still null */}
        return withinJar;
    }

}

【讨论】:

  • 谢谢GreenThor,经过数小时的搜索,这解决了我的问题。
【解决方案2】:

根据您的 cmets,您真正的问题似乎是如何从应用程序 .jar 中复制文件。你可以这样做:

String jarEntry = "/files/data.txt";
Path destination = Paths.get(
    System.getProperty("user.home"), "Downloads", "data.txt");

try (InputStream stream = getClass().getResourceAsStream(jarEntry)) {
    Files.copy(stream, destination);
}

Class.getResource 和 Class.getResourceAsStream 从类路径读取数据,通常作为类路径中 .jar 文件中的一个条目,例如您自己的应用程序的 .jar 文件。

嵌入在类路径中的文件通常称为应用程序资源或简称为“资源”。在所有平台上,甚至在 Windows 上,始终使用正斜杠 (/) 作为目录分隔符来指定资源。

如果您不确定应该将什么字符串传递给 getResource 或 getResourceAsStream,请检查 .jar 文件的内容。

【讨论】:

  • 我有一个复制这些文件夹和文件的工作方法,我只需要我的 JAR 文件的路径来读出它的条目。我不能使用你的方法,因为文件太多,无法手动输入路径。
  • 为什么不打开终端窗口或命令窗口,输入类似dir /b(在Windows 中)或ls -1(其他操作系统)之类的命令,然后将输出复制并粘贴到您的代码中,您可以在其中可以将其格式化为字符串数组吗?您还可以在构建后对您的 .jar 文件执行 jar tf
【解决方案3】:
package com.example;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.net.URL;
import java.util.jar.JarEntry;
import java.util.jar.JarInputStream;

public class HomeJar {

    public static void main(String[] args) throws IOException {

        URL u = HomeJar.class.getProtectionDomain().getCodeSource().getLocation();

        File f = new File(u.getPath().toString());

        if (!f.isFile()) {
            throw new RuntimeException("'" + u + "' isn't a jar");
        }

        try (JarInputStream jis = new JarInputStream(new BufferedInputStream(new FileInputStream(f)))) {
            JarEntry je = jis.getNextJarEntry();
            while (je != null) {
                System.out.println(je.getName());
                je = jis.getNextJarEntry();
            }
        }
    }

}

【讨论】:

  • 如果我运行这个类,它会抛出一个由 RuntimeException 引起的 InvocationTargetException 并且它还说 '"rsrc:./" is not a jar' 所以这和我有同样的问题。跨度>
  • 你用的是什么jdk?
  • 8 更新 77(64 位)
【解决方案4】:

我刚刚创建了一个新的工作区并将每个项目都移入其中,现在一切正常,我认为这是一个错误或其他什么...谢谢大家的帮助!

【讨论】:

    【解决方案5】:

    这正是我今天遇到的问题。我终于找到了这个: 要在使用 Eclipse 打包时获取 jar 文件位置将所需的库打包到生成的 JAR 中,可以使用此方法(在 :

    中插入调用类的名称
    var thisClassesResourcePath = <CLASSNAME>.class.getName().replace('.', '/') + ".class";
    var resource = ClassLoader.getSystemResource(thisClassesResourcePath);
    var path = resource.getPath();
    var jarUrl = new URL(path.substring(0, path.lastIndexOf("jar!") + 3));
    

    【讨论】:

      猜你喜欢
      • 2010-09-24
      • 2012-07-21
      • 1970-01-01
      • 2011-08-06
      • 2015-07-28
      • 1970-01-01
      • 2023-04-09
      相关资源
      最近更新 更多