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

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


当前回答

如果您确实在寻找一种获取JAR所在文件夹的简单方法,那么您应该使用这个实现。 像这样的解决方案很难找到,许多解决方案不再受支持,许多其他解决方案提供文件的路径,而不是实际的目录。这比您将要找到的其他解决方案更容易,并且适用于java版本1.12。

new File(".").getCanonicalPath()

从其他答案中收集输入,这也是一个简单的答案:

String localPath=new File(getClass().getProtectionDomain().getCodeSource().getLocation().toURI()).getParentFile().getPath()+"\\"; 

两者都会返回如下格式的String:

"C:\Users\User\Desktop\Folder\"

用简洁明了的线条。

其他回答

我已经尝试了上面的几种解决方案,但是对于在Eclipse中使用“打包外部库”导出可运行jar的情况(可能是特殊情况),没有一个产生正确的结果。出于某种原因,所有基于ProtectionDomain的解决方案在这种情况下都将导致null。

通过结合上面的一些解决方案,我成功地实现了以下工作代码:

String surroundingJar = null;

// gets the path to the jar file if it exists; or the "bin" directory if calling from Eclipse
String jarDir = new File(ClassLoader.getSystemClassLoader().getResource(".").getPath()).getAbsolutePath();

// gets the "bin" directory if calling from eclipse or the name of the .jar file alone (without its path)
String jarFileFromSys = System.getProperty("java.class.path").split(";")[0];

// If both are equal that means it is running from an IDE like Eclipse
if (jarFileFromSys.equals(jarDir))
{
    System.out.println("RUNNING FROM IDE!");
    // The path to the jar is the "bin" directory in that case because there is no actual .jar file.
    surroundingJar = jarDir;
}
else
{
    // Combining the path and the name of the .jar file to achieve the final result
    surroundingJar = jarDir + jarFileFromSys.substring(1);
}

System.out.println("JAR File: " + surroundingJar);

这里是其他评论的升级版,在我看来,这些评论的细节并不完整

在.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"));

这段代码用于识别程序是否在JAR文件或IDE中执行:

private static boolean isRunningOverJar() {
    try {
        String pathJar = Application.class.getResource(Application.class.getSimpleName() + ".class").getFile();

        if (pathJar.toLowerCase().contains(".jar")) {
            return true;
        } else {
            return false;
        }
    } catch (Exception e) {
        return false;
    }
}

如果我需要获得JAR文件的Windows完整路径,我使用这个方法:

    private static String getPathJar() {
        try {
            final URI jarUriPath =
                    Application.class.getResource(Application.class.getSimpleName() + ".class").toURI();
            String jarStringPath = jarUriPath.toString().replace("jar:", "");
            String jarCleanPath  = Paths.get(new URI(jarStringPath)).toString();

            if (jarCleanPath.toLowerCase().contains(".jar")) {
                return jarCleanPath.substring(0, jarCleanPath.lastIndexOf(".jar") + 4);
            } else {
                return null;
            }
        } catch (Exception e) {
            log.error("Error getting JAR path.", e);
            return null;
        }
    }

我的完整代码使用CommandLineRunner实现与Spring Boot应用程序一起工作,以确保应用程序总是在控制台视图中执行(在JAR文件名中错误地双击),我使用下面的代码:

@SpringBootApplication
public class Application implements CommandLineRunner {
    public static void main(String[] args) throws IOException {
        Console console = System.console();

        if (console == null && !GraphicsEnvironment.isHeadless() && isRunningOverJar()) {
            Runtime.getRuntime().exec(new String[]{"cmd", "/c", "start", "cmd", "/k",
                    "java -jar \"" + getPathJar() + "\""});
        } else {
            SpringApplication.run(Application.class, args);
        }
    }

    @Override
    public void run(String... args) {
        /*
        Additional code here...
        */
    }

    private static boolean isRunningOverJar() {
        try {
            String pathJar = Application.class.getResource(Application.class.getSimpleName() + ".class").getFile();

            if (pathJar.toLowerCase().contains(".jar")) {
                return true;
            } else {
                return false;
            }
        } catch (Exception e) {
            return false;
        }
    }

    private static String getPathJar() {
        try {
            final URI jarUriPath =
                    Application.class.getResource(Application.class.getSimpleName() + ".class").toURI();
            String jarStringPath = jarUriPath.toString().replace("jar:", "");
            String jarCleanPath  = Paths.get(new URI(jarStringPath)).toString();

            if (jarCleanPath.toLowerCase().contains(".jar")) {
                return jarCleanPath.substring(0, jarCleanPath.lastIndexOf(".jar") + 4);
            } else {
                return null;
            }
        } catch (Exception e) {
            return null;
        }
    }
}

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

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

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

我不能转换rsrc:…路径到外部路径,即当在Eclipse IDE外部运行jar文件时,无法获得jar文件的路径。

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

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

这段代码行可能返回的生活路径(包括文件名)运行jar文件(注意,返回路径不是工作目录),作为java文档,有些人说,它将返回所有类文件在同一个目录的路径,但随着我的测试中,如果在相同的目录中包括许多jar文件,它只返回运行jar的路径(约多条路径问题确实发生在Eclipse)。

String path = getClass().getResource("").getPath();

路径总是引用jar文件中的资源。