如何在Java中获取当前工作目录?

我想使用Java访问当前工作目录。

我的代码:

 String currentPath = new java.io.File(".").getCanonicalPath();System.out.println("Current dir:" + currentPath);
String currentDir = System.getProperty("user.dir");System.out.println("Current dir using System:" + currentDir);

输出:

Current dir: C:\WINDOWS\system32Current dir using System: C:\WINDOWS\system32

我的输出不正确,因为C驱动器不是我的当前目录。

如何获取当前目录?

1762024 次浏览

当前的工作目录在不同的Java实现中定义不同。对于Java7之前的某些版本,没有一致的方法来获取工作目录。您可以通过使用-D启动Java文件并定义一个变量来保存信息来解决这个问题

就像

java -D com.mycompany.workingDir="%0"

这不太对,但你明白了。然后System.getProperty("com.mycompany.workingDir")

是什么让你认为c:\windows\system 32文件名不是你当前的目录?#0属性明确表示为“用户当前的工作目录”。

换句话说,除非您从命令行启动Java,否则c:\windows\system 32文件名可能是您的CWD。也就是说,如果您双击启动程序,CWD不太可能是您双击的目录。

编辑:这似乎只适用于旧的windows和/或Java版本。

代码:

public class JavaApplication {public static void main(String[] args) {System.out.println("Working Directory = " + System.getProperty("user.dir"));}}

这将打印初始化应用程序的当前目录的绝对路径。


说明:

留档

java.io包使用当前用户目录解析相对路径名。当前目录表示为系统属性,即user.dir,是调用JVM的目录。

我希望你想访问包含包的当前目录,即如果你的Java程序在c:\myApp\com\foo\src\service\MyTest.java并且你想打印到c:\myApp\com\foo\src\service,那么你可以尝试以下代码:

String myCurrentDir = System.getProperty("user.dir")+ File.separator+ System.getProperty("sun.java.command").substring(0, System.getProperty("sun.java.command").lastIndexOf(".")).replace(".", File.separator);System.out.println(myCurrentDir);

注:此代码仅在使用Oracle JRE的Windows中测试。

见:路径操作(Java™教程>基本类>基本I/O)

使用java.nio.file.Pathjava.nio.file.Paths,您可以执行以下操作来显示Java认为是您当前路径的内容。

Path currentRelativePath = Paths.get("");String s = currentRelativePath.toAbsolutePath().toString();System.out.println("Current absolute path is: " + s);

此输出:

Current absolute path is: /Users/george/NetBeansProjects/Tutorials

在我的情况下,这就是我运行类的地方。

以相对方式构建路径,不使用前导分隔符来指示您正在构建绝对路径,将使用此相对路径作为起点。

this.getClass().getClassLoader().getResource("").getPath()

这是我的解决方案

File currentDir = new File("");

我在Linux,这两种方法都得到相同的结果:

@Testpublic void aaa(){System.err.println(Paths.get("").toAbsolutePath().toString());
System.err.println(System.getProperty("user.dir"));}

Paths.get("")文档

System.getProperty("user.dir") docs

使用#0

这在JAR文件中也可以很好地工作。您可以通过#1获得CodeSource,而ProtectionDomain又可以通过#3获得。

public class Test {public static void main(String... args) throws Exception {URL location = Test.class.getProtectionDomain().getCodeSource().getLocation();System.out.println(location.getFile());}}

以下操作适用于Java7及以上(请参阅这里留档)。

import java.nio.file.Paths;
Paths.get(".").toAbsolutePath().normalize().toString();

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

通常,作为File对象:

File getCwd() {return new File("").getAbsoluteFile();}

您可能希望使用完全限定的字符串,例如“D:/a/b/c”:

getCwd().getAbsolutePath()

这里发布的答案都不适合我。以下是有效的:

java.nio.file.Paths.get(getClass().getProtectionDomain().getCodeSource().getLocation().toURI());

编辑:我的代码中的最终版本:

URL myURL = getClass().getProtectionDomain().getCodeSource().getLocation();java.net.URI myURI = null;try {myURI = myURL.toURI();} catch (URISyntaxException e1){}return java.nio.file.Paths.get(myURI).toFile().toString()

假设您正在尝试在eclipse、netbean或命令行中运行您的项目。我已经编写了一个方法来修复它

public static final String getBasePathForClass(Class<?> clazz) {File file;try {String basePath = null;file = new File(clazz.getProtectionDomain().getCodeSource().getLocation().toURI().getPath());if (file.isFile() || file.getPath().endsWith(".jar") || file.getPath().endsWith(".zip")) {basePath = file.getParent();} else {basePath = file.getPath();}// fix to run inside eclipseif (basePath.endsWith(File.separator + "lib") || basePath.endsWith(File.separator + "bin")|| basePath.endsWith("bin" + File.separator) || basePath.endsWith("lib" + File.separator)) {basePath = basePath.substring(0, basePath.length() - 4);}// fix to run inside netbeanif (basePath.endsWith(File.separator + "build" + File.separator + "classes")) {basePath = basePath.substring(0, basePath.length() - 14);}// end fixif (!basePath.endsWith(File.separator)) {basePath = basePath + File.separator;}return basePath;} catch (URISyntaxException e) {throw new RuntimeException("Cannot firgue out base path for class: " + clazz.getName());}}

要使用,无论你想在哪里获取读取文件的基路径,你都可以将你的锚类传递给上面的方法,结果可能就是你需要的东西:D

最好的,

Linux上,当您从终端运行罐子文件时,这两个文件都将返回相同的String"/home/当前用户",无论您的jar文件在哪里。这取决于您启动jar文件时终端使用的当前目录。

Paths.get("").toAbsolutePath().toString();
System.getProperty("user.dir");

如果你的Classmain被称为MainClass,那么尝试:

MainClass.class.getProtectionDomain().getCodeSource().getLocation().getFile();

这将返回String罐子文件中的绝对路径

使用Windowsuser.dir按预期返回目录,但当您以提升的权限启动应用程序(以管理员身份运行)时不会,在这种情况下,您会得到C:\WINDOWS\system 32

提到它只在Windows中检查,但我认为它在其他操作系统上运行完美[Linux,MacOs,Solaris]:)。


我在同一目录中有2.jar文件。我想从一个.jar文件启动同一目录中的另一个.jar文件。

问题是,当您从cmd启动它时,当前目录是system32


警告!

  • 下面的似乎在我所做的所有测试中工作得很好文件夹名称;][[;'57f2g34g87-8+9-09!2#@!$%^^&()()%&$%^@#效果不错
  • 我使用ProcessBuilder,如下所示:

🍂…

//The class from which i called this was the class `Main`String path = getBasePathForClass(Main.class);String applicationPath=  new File(path + "application.jar").getAbsolutePath();

System.out.println("Directory Path is : "+applicationPath);
//Your know try catch here//Mention that sometimes it doesn't work for example with folder `;][[;'57f2g34g87-8+9-09!2#@!$%^^&()`ProcessBuilder builder = new ProcessBuilder("java", "-jar", applicationPath);builder.redirectErrorStream(true);Process process = builder.start();
//...code

🍂getBasePathForClass(Class<?> classs)

    /*** Returns the absolute path of the current directory in which the given* class* file is.** @param classs* @return The absolute path of the current directory in which the class*         file is.* @author GOXR3PLUS[StackOverFlow user] + bachden [StackOverFlow user]*/public static final String getBasePathForClass(Class<?> classs) {
// Local variablesFile file;String basePath = "";boolean failed = false;
// Let's give a first trytry {file = new File(classs.getProtectionDomain().getCodeSource().getLocation().toURI().getPath());
if (file.isFile() || file.getPath().endsWith(".jar") || file.getPath().endsWith(".zip")) {basePath = file.getParent();} else {basePath = file.getPath();}} catch (URISyntaxException ex) {failed = true;Logger.getLogger(classs.getName()).log(Level.WARNING,"Cannot firgue out base path for class with way (1): ", ex);}
// The above failed?if (failed) {try {file = new File(classs.getClassLoader().getResource("").toURI().getPath());basePath = file.getAbsolutePath();
// the below is for testing purposes...// starts with File.separator?// String l = local.replaceFirst("[" + File.separator +// "/\\\\]", "")} catch (URISyntaxException ex) {Logger.getLogger(classs.getName()).log(Level.WARNING,"Cannot firgue out base path for class with way (2): ", ex);}}
// fix to run inside eclipseif (basePath.endsWith(File.separator + "lib") || basePath.endsWith(File.separator + "bin")|| basePath.endsWith("bin" + File.separator) || basePath.endsWith("lib" + File.separator)) {basePath = basePath.substring(0, basePath.length() - 4);}// fix to run inside netbeansif (basePath.endsWith(File.separator + "build" + File.separator + "classes")) {basePath = basePath.substring(0, basePath.length() - 14);}// end fixif (!basePath.endsWith(File.separator)) {basePath = basePath + File.separator;}return basePath;}

这将为您提供当前工作目录的路径:

Path path = FileSystems.getDefault().getPath(".");

这将为您提供工作目录中名为“Foo.txt”的文件的路径:

Path path = FileSystems.getDefault().getPath("Foo.txt");

编辑:获取当前目录的绝对路径:

Path path = FileSystems.getDefault().getPath(".").toAbsolutePath();

*更新*获取当前工作目录:

Path path = FileSystems.getDefault().getPath("").toAbsolutePath();

Java11及更新

这个解决方案比其他解决方案更好,更便携:

Path cwd = Path.of("").toAbsolutePath();

或者甚至

String cwd = Path.of("").toAbsolutePath().toString();

这是我在混乱时刻的银弹。(将其称为main中的第一件事)。也许例如JVM被IDE滑到不同的版本。这个静态函数搜索当前进程PID并在该pid上打开VisualVM。混乱就在那里停止,因为你想要一切,你得到了它…

  public static void callJVisualVM() {System.out.println("USER:DIR!:" + System.getProperty("user.dir"));//next search current jdk/jreString jre_root = null;String start = "vir";try {java.lang.management.RuntimeMXBean runtime =java.lang.management.ManagementFactory.getRuntimeMXBean();String jvmName = runtime.getName();System.out.println("JVM Name = " + jvmName);long pid = Long.valueOf(jvmName.split("@")[0]);System.out.println("JVM PID  = " + pid);Runtime thisRun = Runtime.getRuntime();jre_root = System.getProperty("java.home");System.out.println("jre_root:" + jre_root);start = jre_root.concat("\\..\\bin\\jvisualvm.exe " + "--openpid " + pid);thisRun.exec(start);} catch (Exception e) {System.getProperties().list(System.out);e.printStackTrace();}}

这并不完全是问的,但这里有一个重要的注意事项:当在Windows机器上运行Java时,Oracle安装程序将一个“java.exe”放入C:\Windows\system 32中,这就是Java应用程序的启动器(除非PATH中前面有一个java.exe,并且Java应用程序是从命令行运行的)。这就是为什么File(“.”)不断返回C:\Windows\system 32,为什么从macOS或*nix实现运行示例不断从Windows返回不同的结果。

不幸的是,就我在二十年的Java编码中发现的而言,这个问题真的没有普遍正确的答案,除非你想使用JNI调用创建自己的本机启动器可执行文件,并在启动时从本机启动器代码中获取当前工作目录。

尝试这样的事情我知道我迟到了,但这明显的事情发生在java8一个新版本中,这个问题被问到但是…

该代码

import java.io.File;
public class Find_this_dir {
public static void main(String[] args) {
//some sort of a bug in java path is correct but file dose not existFile this_dir = new File("");
//but these both commands work too to get current dir//      File this_dir_2 = new File(this_dir.getAbsolutePath());File this_dir_2 = new File(new File("").getAbsolutePath());
System.out.println("new File(" + "\"\"" + ")");System.out.println(this_dir.getAbsolutePath());System.out.println(this_dir.exists());System.out.println("");System.out.println("new File(" + "new File(" + "\"\"" + ").getAbsolutePath()" + ")");System.out.println(this_dir_2.getAbsolutePath());System.out.println(this_dir_2.exists());}}

这将工作并向您显示当前路径,但我现在不知道为什么Java无法在#0中找到当前目录,除了我使用Java8编译器…

这工作得很好,我甚至测试了它new File(new File("").getAbsolutePath());

现在您在File对象中拥有当前目录,因此(示例文件对象是f),

f.getAbsolutePath()将为您提供String可变类型的路径…

在另一个不是驱动器的目录中测试C工作正常

对于Java11,您还可以使用:

var path = Path.of(".").toRealPath();

我最喜欢的方法是从附加到当前运行进程的系统环境变量中获取它。在这种情况下,您的应用程序由JVM管理。

String currentDir = System.getenv("PWD");/*/home/$User/Documents/java*/

要查看其他可能有用的环境变量,例如home dir、os version……

//Home directoryString HomeDir = System.getEnv("HOME");

//Outputs for unix/home/$USER
//Device userString user = System.getEnv("USERNAME");

//Outputs for unix$USER

这种方法的美妙之处在于,所有路径都将为所有类型的操作系统平台解决

您可以使用new File("./")。这样isDirectory()返回true(至少在Windows平台上)。另一方面new File("") isDirectory()返回false。

这是一个非常混乱的话题,在提供真正的解决方案之前,我们需要了解一些概念。

  1. File和NIO File Api以相对路径"""."接近,在内部使用系统参数"user.dir"值来确定返回位置。

  2. "user.dir"值基于USER工作目录,该值的行为取决于操作系统和jar的执行方式。

  3. 例如,使用文件资源管理器从Linux执行JAR(通过双击打开它)将使用用户主目录设置user.dir,而不管jar的位置。如果从命令行执行相同的jar,它将返回jar位置,因为每个cd命令到jar位置都会修改工作目录。

话虽如此,使用Java NIOFiles"user.dir"属性的解决方案将以"user.dir"具有正确值的方式适用于所有场景。

String userDirectory = System.getProperty("user.dir");String userDirectory2 = new File("").getAbsolutePath();String userDirectory3 = Paths.get("").toAbsolutePath().toString();

我们可以使用以下代码:

new File(MyApp.class.getProtectionDomain().getCodeSource().getLocation().toURI().getPath()).getParent();

为了获取执行的JAR的当前位置,我个人使用以下方法来获取预期位置并在应用程序的一开始覆盖"user.dir"系统属性。因此,稍后使用其他方法时,我将始终获得期望值。

更多详情>https://blog.adamgamboa.dev/getting-current-directory-path-in-java/

    public class MyApp {      
static {//This static block runs at the very begin of the APP, even before the main method.try{File file = new File(MyApp.class.getProtectionDomain().getCodeSource().getLocation().toURI().getPath());String basePath = file.getParent();//Overrides the existing value of "user.dir"System.getProperties().put("user.dir", basePath);}catch(URISyntaxException ex){//log the error}}     
public static void main(String args []){//Your app logic        
//All these approaches should return the expected value//regardless of the way the jar is executed.String userDirectory = System.getProperty("user.dir");String userDirectory2 = new File("").getAbsolutePath();String userDirectory3 = Paths.get("").toAbsolutePath().toString();}}

我希望这个解释和细节对其他人有所帮助…