当前位置:  开发笔记 > 编程语言 > 正文

如何获取正在运行的JAR文件的路径?

如何解决《如何获取正在运行的JAR文件的路径?》经验,为你挑选了11个好方法。

我的代码在一个JAR文件中运行,比如说foo.jar,我需要在代码中知道运行foo.jar的文件夹.

所以,如果foo.jar在C:\FOO\,我想要获得该路径,无论我当前的工作目录是什么.



1> Zarkonnen..:
return new File(MyClass.class.getProtectionDomain().getCodeSource().getLocation()
    .toURI()).getPath();

将"MyClass"替换为您班级的名称

显然,如果您的类是从非文件位置加载的,那么这会很奇怪.


`toURI()`步骤对于避免特殊字符(包括空格和加号)的问题至关重要.正确的一行是:`return new File(MyClass.class.getProtectionDomain().getCodeSource().getLocation().toURI());`使用`URLDecoder`不适用于许多特殊字符.有关详细信息,请参阅下面的答案.
这不是指向jar文件而不是运行目录吗?您将不得不对结果getParentFile()执行此工作.
注意:这将返回包含jar文件名称的路径

2> 小智..:

最适合我的解决方案:

String path = Test.class.getProtectionDomain().getCodeSource().getLocation().getPath();
String decodedPath = URLDecoder.decode(path, "UTF-8");

这应该解决空格和特殊字符的问题.


/不一定是路径分隔符.你应该做(新文件(路径)).getParentFile().getPath().
注意:不建议使用`URLDecoder`来解码特殊字符.特别是像`+`这样的字符会被错误地解码为空格.详情请见我的回答.
这里没有附加JAR文件名的问题.在Linux上,UTF转换似乎是与@Iviggiani one(`URLDecoder.decode(ClassLoader.getSystemClassLoader().getResource(".").getPath(),"UTF-8");`组合的完美解决方案.但是,我没有试过Windows.
还有一点需要注意:从Jar调用此函数时,jar的名称会附加在我的末尾,因此必须执行:path.substring(0,path.lastIndexOf("/")+ 1);
谢谢,这允许我在Linux和Windows中使用FileInputStream加载我的JAR外部文件.只需在文件名前添加解码路径......

3> ctrueden..:

要获得File给定的Class,有两个步骤:

    转换Class为aURL

    转换URL为aFile

理解这两个步骤很重要,而不是将它们混为一谈.

一旦你有了File,你可以打电话getParentFile来获取包含文件夹,如果这是你需要的.

第1步:ClassURL

正如其他答案中所讨论的,有两种主要方法可以找到与a URL相关的方法Class.

    URL url = Bar.class.getProtectionDomain().getCodeSource().getLocation();

    URL url = Bar.class.getResource(Bar.class.getSimpleName() + ".class");

两者都有利有弊.

getProtectionDomain方法产生类的基本位置(例如,包含JAR文件).但是,Java运行时的安全策略可能会SecurityException在调用时抛出getProtectionDomain(),因此如果您的应用程序需要在各种环境中运行,最好在所有环境中进行测试.

getResource方法生成类的完整URL资源路径,您将需要从该路径执行其他字符串操作.它可能是一条file:路径,但它也可能是jar:file:甚至更糟糕的东西,就像bundleresource://346.fwk2106232034:4/foo/Bar.class在OSGi框架内执行一样.相反,即使在OSGi中,该getProtectionDomain方法也能正确生成file:URL.

请注意这两个getResource("")getResource(".")在我的测试中失败了,上课的时候一个JAR文件中居住; 两个调用都返回null.所以我推荐上面显示的#2调用,因为它似乎更安全.

第2步:URLFile

无论哪种方式,一旦你有了URL,下一步就是转换为File.这是它自己的挑战; 有关详细信息,请参阅Kohsuke Kawaguchi的博客文章,但简而言之,new File(url.toURI())只要URL完全格式化,您就可以使用它.

最后,我强烈反对使用URLDecoder.URL的某些字符,:并且/特别是无效的URL编码字符.从URLDecoder Javadoc:

假设编码的字符串中的所有字符是下列之一:"a"至"Z","A"到"Z","0"至"9",和" - ","_"," ."和"*".允许使用字符"%",但将其解释为特殊转义序列的开头.

...

这种解码器有两种可能的方式来处理非法字符串.它可能会单独留下非法字符,也可能会抛出IllegalArgumentException.解码器采用哪种方法留给实现.

在实践中,URLDecoder一般不会IllegalArgumentException像上面那样受到威胁.如果你的文件路径有空格编码%20,这种方法似乎可行.但是,如果您的文件路径具有其他非字母数字字符,例如+您将在URLDecoder修改文件路径时遇到问题.

工作代码

要实现这些步骤,您可能拥有以下方法:

/**
 * Gets the base location of the given class.
 * 

* If the class is directly on the file system (e.g., * "/path/to/my/package/MyClass.class") then it will return the base directory * (e.g., "file:/path/to"). *

*

* If the class is within a JAR file (e.g., * "/path/to/my-jar.jar!/my/package/MyClass.class") then it will return the * path to the JAR (e.g., "file:/path/to/my-jar.jar"). *

* * @param c The class whose location is desired. * @see FileUtils#urlToFile(URL) to convert the result to a {@link File}. */ public static URL getLocation(final Class c) { if (c == null) return null; // could not load the class // try the easy way first try { final URL codeSourceLocation = c.getProtectionDomain().getCodeSource().getLocation(); if (codeSourceLocation != null) return codeSourceLocation; } catch (final SecurityException e) { // NB: Cannot access protection domain. } catch (final NullPointerException e) { // NB: Protection domain or code source is null. } // NB: The easy way failed, so we try the hard way. We ask for the class // itself as a resource, then strip the class's path from the URL string, // leaving the base path. // get the class's raw resource path final URL classResource = c.getResource(c.getSimpleName() + ".class"); if (classResource == null) return null; // cannot find class resource final String url = classResource.toString(); final String suffix = c.getCanonicalName().replace('.', '/') + ".class"; if (!url.endsWith(suffix)) return null; // weird URL // strip the class's path from the URL string final String base = url.substring(0, url.length() - suffix.length()); String path = base; // remove the "jar:" prefix and "!/" suffix, if present if (path.startsWith("jar:")) path = path.substring(4, path.length() - 2); try { return new URL(path); } catch (final MalformedURLException e) { e.printStackTrace(); return null; } } /** * Converts the given {@link URL} to its corresponding {@link File}. *

* This method is similar to calling {@code new File(url.toURI())} except that * it also handles "jar:file:" URLs, returning the path to the JAR file. *

* * @param url The URL to convert. * @return A file path suitable for use with e.g. {@link FileInputStream} * @throws IllegalArgumentException if the URL does not correspond to a file. */ public static File urlToFile(final URL url) { return url == null ? null : urlToFile(url.toString()); } /** * Converts the given URL string to its corresponding {@link File}. * * @param url The URL to convert. * @return A file path suitable for use with e.g. {@link FileInputStream} * @throws IllegalArgumentException if the URL does not correspond to a file. */ public static File urlToFile(final String url) { String path = url; if (path.startsWith("jar:")) { // remove "jar:" prefix and "!/" suffix final int index = path.indexOf("!/"); path = path.substring(4, index); } try { if (PlatformUtils.isWindows() && path.matches("file:[A-Za-z]:.*")) { path = "file:/" + path.substring(5); } return new File(new URL(path).toURI()); } catch (final MalformedURLException e) { // NB: URL is not completely well-formed. } catch (final URISyntaxException e) { // NB: URL is not completely well-formed. } if (path.startsWith("file:")) { // pass through the URL as-is, minus "file:" prefix path = path.substring(5); return new File(path); } throw new IllegalArgumentException("Invalid URL: " + url); }

您可以在SciJava Common库中找到这些方法:

org.scijava.util.ClassUtils

org.scijava.util.FileUtils.


+1; 日期的最佳答案:它将使用操作系统的正确表示法返回路径.(例如\用于Windows).

4> Benny Neugeb..:

您还可以使用:

CodeSource codeSource = YourMainClass.class.getProtectionDomain().getCodeSource();
File jarFile = new File(codeSource.getLocation().toURI().getPath());
String jarDir = jarFile.getParentFile().getPath();


这对我来说效果更好,因为它给出了Jar的路径,而不是类的路径!

5> Jon Skeet..:

使用ClassLoader.getResource()查找当前类的URL.

例如:

package foo;

public class Test
{
    public static void main(String[] args)
    {
        ClassLoader loader = Test.class.getClassLoader();
        System.out.println(loader.getResource("foo/Test.class"));
    }
}

(这个例子来自一个类似的问题.)

要查找目录,您需要手动拆分URL.有关jar URL的格式,请参阅JarClassLoader教程.


如果它被混淆了,请使用Test.class.getName()并进行适当的修改.
@WhiteAngel:这是我写过的最好的答案吗?不.它是否像你要成功一样糟糕?不,我不这么认为.(特别是关于你在它周围抛出NPE的声明而言,它没有.)我建议你添加自己的答案,而不是对这个问题大惊小怪.这将是一个更积极的方法.

6> mat_boy..:

我很惊讶地看到最近没有提议使用Path.这里如下引文:" Path类包括可以用来获得关于所述路径信息的各种方法,该路径的接入元件,所述路径转换为其它形式的,或提取的路径的部分 "

因此,一个好的选择是将Path目标视为:

Path path = Paths.get(Test.class.getProtectionDomain().getCodeSource().getLocation().toURI());


注意,Path从Java 7开始可用.

7> Dmitry Trofi..:

在Linux,Mac和Windows上唯一适用于我的解决方案:

public static String getJarContainingFolder(Class aclass) throws Exception {
  CodeSource codeSource = aclass.getProtectionDomain().getCodeSource();

  File jarFile;

  if (codeSource.getLocation() != null) {
    jarFile = new File(codeSource.getLocation().toURI());
  }
  else {
    String path = aclass.getResource(aclass.getSimpleName() + ".class").getPath();
    String jarFilePath = path.substring(path.indexOf(":") + 1, path.indexOf("!"));
    jarFilePath = URLDecoder.decode(jarFilePath, "UTF-8");
    jarFile = new File(jarFilePath);
  }
  return jarFile.getParentFile().getAbsolutePath();
}



8> Zon..:

这是对其他评论的升级,对于我来说,这似乎是不完整的

使用.jar文件外的相对"文件夹"(在jar的相同位置):

String path = 
  YourMainClassName.class.getProtectionDomain().
  getCodeSource().getLocation().getPath();

path = 
  URLDecoder.decode(
    path, 
    "UTF-8");

BufferedImage img = 
  ImageIO.read(
    new File((
        new File(path).getParentFile().getPath()) +  
        File.separator + 
        "folder" + 
        File.separator + 
        "yourfile.jpg"));


注意:不建议使用`URLDecoder`来解码特殊字符.特别是像`+`这样的字符会被错误地解码为空格.详情请见我的回答.

9> Charlie..:

我有同样的问题,我解决了这个问题:

File currentJavaJarFile = new File(Main.class.getProtectionDomain().getCodeSource().getLocation().getPath());   
String currentJavaJarFilePath = currentJavaJarFile.getAbsolutePath();
String currentRootDirectoryPath = currentJavaJarFilePath.replace(currentJavaJarFile.getName(), "");

我希望我对你有所帮助.



10> 小智..:

为了获得运行jar文件的路径,我研究了上述解决方案并尝试了所有存在一些差异的方法.如果这些代码在Eclipse IDE中运行,那么它们都应该能够找到包含指定类的文件路径,并打开或创建带有找到路径的指示文件.

但是很棘手,当直接或通过命令行运行runnable jar文件时,它会失败,因为从上面的方法获取的jar文件的路径将在jar文件中给出一个内部路径,也就是它总是给出一个路径如

rsrc:project-name(也许我应该说它是主类文件的包名 - 指示的类)

我无法将rsrc:...路径转换为外部路径,即在Eclipse IDE外部运行jar文件时无法获取jar文件的路径.

获取在Eclipse IDE外部运行jar文件的路径的唯一可能方法是

System.getProperty("java.class.path")

这段代码行可能会返回正在运行的jar文件的生存路径(包括文件名)(注意返回路径不是工作目录),因为java文件和一些人说它会返回所有类文件的路径在同一目录中,但作为我的测试,如果在同一目录中包含许多jar文件,它只返回运行jar的路径(关于多路径问题确实发生在Eclipse中).



11> F.O.O..:

其他答案似乎指向代码源,它是Jar文件位置,而不是目录。

使用

return new File(MyClass.class.getProtectionDomain().getCodeSource().getLocation().toURI().getPath()).getParentFile();

推荐阅读
李桂平2402851397
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有