获取正在运行的JAR文件的路径将返回" rsrc:./"

时间:2016-06-19 00:04:02

标签: java jar path manifest rsrc

我的代码在JAR文件中运行,我需要获取该文件的完整路径。 例如,我的JAR名为example.jar,位于D:\ example \ 所以我需要得到" D:\ example \ example.jar"通过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的东西并用它替换其他东西,它就说罐子坏了。我认为这就是它不起作用的原因。有人知道这意味着什么吗?

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

4 个答案:

答案 0 :(得分:5)

我偶然发现了这个问题,并将此调查留给了那些在将来问自己rsrc意味着什么的人。

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

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

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

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

    结果:

    1. file:/C:/Users/admin/Desktop/MyJar.jar
    2. rsrc:./
    3. file:/C:/Users/admin/Desktop/MyJar.jar
    4. <意味着在Eclipse中运行> file:/C:/Development/workspace/MyProject/target/classes/
    5. 我为此写了一个方便的方法:

      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;
          }
      
      }
      

答案 1 :(得分:0)

根据您的评论,您似乎真正的问题是如何从应用程序内部复制文件.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文件的内容。

答案 2 :(得分:0)

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();
            }
        }
    }

}

答案 3 :(得分:0)

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