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

所以,如果FOO .jar在C:\FOO\中,无论我当前的工作目录是什么,我都想获得这个路径。


当前回答

对于jar文件路径:

String jarPath = new File(MyClass.class.getProtectionDomain().getCodeSource().getLocation()
    .toURI()).getPath();

获取jar文件的目录路径:

String dirPath = new File(MyClass.class.getProtectionDomain().getCodeSource().getLocation()
                        .toURI()).getParent();

上面两行的结果是这样的:

/home/user/MyPrograms/myapp/myjar.jar (jarPath的值)

/home/user/MyPrograms/myapp (dirPath的值)

其他回答

实际上,这里有一个更好的版本-如果文件夹名中有空格,旧的版本就会失败。

  private String getJarFolder() {
    // get name and path
    String name = getClass().getName().replace('.', '/');
    name = getClass().getResource("/" + name + ".class").toString();
    // remove junk
    name = name.substring(0, name.indexOf(".jar"));
    name = name.substring(name.lastIndexOf(':')-1, name.lastIndexOf('/')+1).replace('%', ' ');
    // remove escape characters
    String s = "";
    for (int k=0; k<name.length(); k++) {
      s += name.charAt(k);
      if (name.charAt(k) == ' ') k += 2;
    }
    // replace '/' with system separator char
    return s.replace('/', File.separatorChar);
  }

至于applet失败的原因,您通常无法访问本地文件。我不太了解JWS,但要处理本地文件,可能无法下载该应用程序。

要获得给定类的文件,有两个步骤:

将类转换为URL 将URL转换为文件

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

有了文件之后,如果需要的话,可以调用getParentFile来获取包含该文件的文件夹。

步骤1:类到URL

正如在其他答案中讨论的那样,有两种主要方法来查找与类相关的URL。

URL URL = Bar.class.getProtectionDomain().getCodeSource().getLocation(); URL URL = Bar.class.getResource(Bar.class.getSimpleName() + ".class");

两者都有利弊。

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

getResource方法生成类的完整URL资源路径,您需要从该路径执行额外的字符串操作。它可以是file: path,但也可以是jar:file:,甚至在OSGi框架中执行时,可以是bundleresource://346.fwk2106232034:4/foo/Bar.class。相反,getProtectionDomain方法甚至可以从OSGi内部正确地生成一个file: URL。

注意,当类驻留在JAR文件中时,getResource("")和getResource(".")在我的测试中都失败了;两次调用都返回null。因此,我推荐使用上面所示的#2调用,因为它似乎更安全。

步骤2:URL到文件

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

最后,我强烈反对使用URLDecoder。URL的某些字符,特别是:和/,不是有效的URL编码字符。从URLDecoder Javadoc:

假设编码字符串中的所有字符都是以下字符之一:"a"到"z", "a"到"z", "0"到"9",以及"-","_","."和"*"。字符“%”是允许的,但被解释为特殊转义序列的开始。 ... 这个解码器有两种可能的方法来处理非法字符串。它可以不处理非法字符,也可以抛出一个IllegalArgumentException异常。解码器采用哪种方法取决于实现。

在实践中,URLDecoder通常不会像上面威胁的那样抛出IllegalArgumentException。如果文件路径中有编码为%20的空格,则此方法似乎可以工作。然而,如果你的文件路径有其他非字母字符,如+,你将有问题与URLDecoder破坏你的文件路径。

工作代码

为了实现这些步骤,你可以使用如下方法:

/**
 * Gets the base location of the given class.
 * <p>
 * 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").
 * </p>
 * <p>
 * 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").
 * </p>
 *
 * @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}.
 * <p>
 * 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.
 * </p>
 * 
 * @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公共库中找到这些方法:

org.scijava.util.ClassUtils org.scijava.util.FileUtils。

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

Use

return new File(MyClass.class.getProtectionDomain().getCodeSource().getLocation().toURI().getPath()).getParentFile();
public static String dir() throws URISyntaxException
{
    URI path=Main.class.getProtectionDomain().getCodeSource().getLocation().toURI();
    String name= Main.class.getPackage().getName()+".jar";
    String path2 = path.getRawPath();
    path2=path2.substring(1);

    if (path2.contains(".jar"))
    {
        path2=path2.replace(name, "");
    }
    return path2;}

在Windows上运行良好

我很惊讶地发现,最近没有人建议使用Path。以下是引用:“Path类包括各种方法,可用于获取路径信息、访问路径元素、将路径转换为其他形式或提取路径的部分”

因此,一个好的替代方法是获取Path对象为:

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