【问题标题】:Get location of JAR file获取 JAR 文件的位置
【发布时间】:2013-02-27 21:01:28
【问题描述】:

我正在尝试获取 Runnable JAR 文件的运行位置。 我试过做

try {
    String path = new java.io.File(".").getCanonicalPath();
} catch (IOException e) {
    e.printStackTrace();
}

但是返回:

C:\Users\Kevin\Desktop/server/Server

JAR 文件位于

C:\Users\Kevin\Desktop

我也试过了

return new file(Server.class.getProtectionDomain().getCodeSource().getLocation().getPath());

但是返回:

C:\Users\Kevin\Desktop\server.jar/server/Server

所以基本上我想要没有文件名而不是 ClassPath 的 JAR 文件的路径。

有什么办法吗?

【问题讨论】:

  • 这可能会有所帮助,之前的讨论。 stackoverflow.com/questions/320542/… //Henrik
  • 规范不完整。如果您不是从 JAR 运行,应该怎么做?如果 JAR 存在于某个网络中怎么办?
  • 嗯,事情是我正在尝试创建一个包含文件的目录,并且该目录必须在我的桌面上或我从中运行 JAR 的任何地方。如果我在 Eclipse 中以调试模式运行它,它会在 bin/server 文件夹中创建文件。
  • 但是你总是从“.”跑,所以.....问题出在哪里?

标签: java class jar path directory


【解决方案1】:

更新

由于它在某些测试用例中不起作用,我将更新答案。

正确的做法应该是ClassLoader:

File jarDir = new File(ClassLoader.getSystemClassLoader().getResource(".").getPath());
System.out.println(jarDir.getAbsolutePath());

在各种类路径上测试,输出正确。


旧答案

这应该可以工作

File f = new File(System.getProperty("java.class.path"));
File dir = f.getAbsoluteFile().getParentFile();
String path = dir.toString();

它对我有用,我的程序在:

C:\Users\User01\Documents\app1\dist\JavaApplication1.jar

然后它返回

C:\Users\User01\Documents\app1\dist

【讨论】:

  • 这只有在你的类路径只包含一个条目时才有效。
  • @BackSlash 你有没有在 linux/unix 系统上尝试过上面的代码,它可以完美运行吗?
  • @dbw 类路径可以是 jar 文件、zip 文件和目录的列表,在 Unix 中用 ':' 或 ';' 分隔在 Windows 中。显然new File("foo.jar:bar/:baz.jar") 不会工作。
  • 当你这样设置时,例如运行java -cp foo.jar:bar/:baz.jar .....
  • getResource(".") 在我的情况下返回 null
【解决方案2】:

这里是我计算jar目录的版本

/**
 * Compute the absolute file path to the jar file.
 * The framework is based on http://stackoverflow.com/a/12733172/1614775
 * But that gets it right for only one of the four cases.
 * 
 * @param aclass A class residing in the required jar.
 * 
 * @return A File object for the directory in which the jar file resides.
 * During testing with NetBeans, the result is ./build/classes/,
 * which is the directory containing what will be in the jar.
 */
public static File getJarDir(Class aclass) {
    URL url;
    String extURL;      //  url.toExternalForm();

    // get an url
    try {
        url = aclass.getProtectionDomain().getCodeSource().getLocation();
          // url is in one of two forms
          //        ./build/classes/   NetBeans test
          //        jardir/JarName.jar  froma jar
    } catch (SecurityException ex) {
        url = aclass.getResource(aclass.getSimpleName() + ".class");
        // url is in one of two forms, both ending "/com/physpics/tools/ui/PropNode.class"
        //          file:/U:/Fred/java/Tools/UI/build/classes
        //          jar:file:/U:/Fred/java/Tools/UI/dist/UI.jar!
    }

    // convert to external form
    extURL = url.toExternalForm();

    // prune for various cases
    if (extURL.endsWith(".jar"))   // from getCodeSource
        extURL = extURL.substring(0, extURL.lastIndexOf("/"));
    else {  // from getResource
        String suffix = "/"+(aclass.getName()).replace(".", "/")+".class";
        extURL = extURL.replace(suffix, "");
        if (extURL.startsWith("jar:") && extURL.endsWith(".jar!"))
            extURL = extURL.substring(4, extURL.lastIndexOf("/"));
    }

    // convert back to url
    try {
        url = new URL(extURL);
    } catch (MalformedURLException mux) {
        // leave url unchanged; probably does not happen
    }

    // convert url to File
    try {
        return new File(url.toURI());
    } catch(URISyntaxException ex) {
        return new File(url.getPath());
    }
}

【讨论】:

    【解决方案3】:

    在我终于找到一个可行的解决方案之前,我不得不搞砸了很多。
    jarLocation 可能带有 file:\jar:file\ 之类的前缀,可以使用 String#substring() 删除。

    URL jarLocationUrl = MyClass.class.getProtectionDomain().getCodeSource().getLocation();
    String jarLocation = new File(jarLocationUrl.toString()).getParent();
    

    【讨论】:

    • .getParent() 是我获取 Runnable JAR 路径所必需的。
    【解决方案4】:

    如果你知道

    file(Server.class.getProtectionDomain().getCodeSource().getLocation().getPath());
    

    返回

    C:\Users\Kevin\Desktop\server.jar/server/Server
    

    而且您知道您的 Jar 名称是 server.jar 或任何 .jar 文件,您的意图是获取 C:\Users\Kevin\Desktop ,直接的方法是进行字符串操作。

    使用检索到的输出,根据 File.separator 标记字符串并构造路径(通过将字符串与中间的 File.separator 连接),直到获得包含 .jar 的标记

    【讨论】:

    • 是的,但是如果用户决定更改 JAR 的名称怎么办?
    • 您不应该使用硬编码的 jar 文件名进行搜索,理想情况下,在检索到令牌后,您应该检查该 token.contains(.jar),这将适用于您的 jar 文件名
    • 不,它不会,例如,如果它被重命名为 ZIP
    • 这是一个简单的字符串操作,您需要处理所有可能的文件扩展名以满足您的要求。一般来说,只要处理 jar 和 zip 就足够了
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-02-15
    • 2010-10-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多