如何在 Java 中获取当前工作目录?
Posted
技术标签:
【中文标题】如何在 Java 中获取当前工作目录?【英文标题】:How to get the current working directory in Java? 【发布时间】:2011-06-19 18:06:08 【问题描述】:我想使用 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\system32
Current dir using System: C:\WINDOWS\system32
我的输出不正确,因为 C 盘不是我的当前目录。
如何获取当前目录?
【问题讨论】:
您试图通过访问工作目录来完成什么?可以通过使用类路径来完成吗?例如,如果你需要读取文件系统上的一个文本文件,你可以在类路径上轻松找到它。 怎么样?能详细点吗? 有关访问类路径上的文件的一些信息,请参阅***.com/questions/1464291/… 出于调试目的,工作目录可能有助于了解程序是否似乎无法访问存在的文件。 两种方法(以及下面的方法)看起来都是正确的。如果您将系统目录设为 CWD,那么这可能是由于包装器在启动 Java 之前做了 CD。例如 javapath 可能会这样做。直接将 java.exe 的路径指定到实际的 Java_:home 目录以避免这种情况。 【参考方案1】:请参阅:Path Operations (The Java™ Tutorials > Essential Classes > Basic I/O)。
使用java.nio.file.Path
和java.nio.file.Paths
,您可以执行以下操作来显示Java 认为您当前的路径。这适用于 7 及更高版本,并使用 NIO。
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
就我而言,这就是我开始上课的地方。
以相对方式构建路径,通过不使用前导分隔符表示您正在构建绝对路径,将使用此相对路径作为起点。
【讨论】:
第一个没有检查,但第二个实际上会获取您的主文件夹。不是当前运行应用程序的工作目录。 请不要混淆用户的主目录(“user.home”,在你的情况下是 /Users/george)和当前工作目录(“user.dir”,它将是来自的目录您为应用程序启动了 JVM,因此可能类似于 /Users/george/workspace/FooBarProject)。 我更喜欢这种方式。当我需要工作目录的父级时,这不起作用:Paths.get("").getParent()
,它提供null
。取而代之的是:Paths.get("").toAbsolutePath().getParent()
.【参考方案2】:
我最喜欢的方法是从附加到当前运行进程的系统环境变量中获取它。在这种情况下,您的应用程序由 JVM 管理。
String currentDir = System.getenv("PWD");
/*
/home/$User/Documents/java
*/
查看您可能会发现有用的其他环境变量,例如主目录、操作系统版本........
//Home directory
String HomeDir = System.getEnv("HOME");
//Outputs for unix
/home/$USER
//Device user
String user = System.getEnv("USERNAME");
//Outputs for unix
$USER
这种方法的美妙之处在于,所有路径都将针对所有类型的操作系统平台进行解析
【讨论】:
【参考方案3】:Java 11 及更新版本
此解决方案比其他解决方案更好,更便携:
Path cwd = Path.of("").toAbsolutePath();
甚至
String cwd = Path.of("").toAbsolutePath().toString();
【讨论】:
这与 comeGetSome 的答案完全相同,实际上是 Java 应该是 Path cwd = Paths.get("").toAbsolutePath(); 最好使用Path.of
,因为Paths might get deprecated。此外,Paths.get
只需调用 Path.of
。
@onkarruikar 好点,我会更新答案【参考方案4】:
对于 Java 11,您还可以使用:
var path = Path.of(".").toRealPath();
【讨论】:
【参考方案5】:尝试这样的事情我知道我迟到了答案但是这个明显的事情发生在 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 exist
File 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 无法在 new File("");
中找到当前目录,除了我使用的是 Java8 编译器。 ..
这很好用,我什至测试过new File(new File("").getAbsolutePath());
现在您在 File 对象中有当前目录,因此(示例文件对象为 f),
f.getAbsolutePath()
将为您提供字符串变量类型的路径...
在另一个不是驱动器 C 的目录中测试工作正常
【讨论】:
【参考方案6】:代码:
public class JavaApplication
public static void main(String[] args)
System.out.println("Working Directory = " + System.getProperty("user.dir"));
这将打印应用程序初始化的当前目录的绝对路径。
说明:
来自documentation:
java.io
包使用当前用户目录解析相对路径名。当前目录表示为系统属性,即user.dir
,是调用JVM的目录。
【讨论】:
@ubuntudroid:这就是为什么我特别提到它将打印应用程序初始化的路径。我猜线程启动器在启动 commnad 提示符后直接运行 jar/程序(基本上在 C:\WINDOWS\system32 处)。我希望你明白我的意思。假设您投了反对票,请感谢您至少愿意留下回应。 :) user.dir 将获取启动进程的文件夹的路径。要获取应用程序主文件夹的实际路径,请参阅下面的答案。 我的意思是“所有依赖它查找当前目录的代码都失败了。”。一般而言,并非所有代码。 (我编辑原来的评论太慢了) @SubOptimal 如果用户设置了 -Duser.dir,则可能他想在自定义工作目录中运行它。 @indyaah 事实上这个答案是错误的,系统进程(cwd)的用户工作目录和当前工作目录之间存在细微差别;大多数时候“user.dir”指向(java)进程的cwd;但“user.dir”语义不同,不能用于获取java进程的cwd; btw:java进程docs.oracle.com/javase/tutorial/essential/environment/…还有更多属性可供参考【参考方案7】:这并不是所要求的,但这里有一个重要说明:在 Windows 机器上运行 Java 时,Oracle 安装程序会将“java.exe”放入 C:\Windows\system32,这就是作为Java 应用程序的启动器(除非 PATH 中有一个 java.exe,并且 Java 应用程序是从命令行运行的)。这就是为什么 File(".") 不断返回 C:\Windows\system32,和为什么从 macOS 或 *nix 实现运行示例不断返回与 Windows 不同的结果。
不幸的是,就我在 20 年的 Java 编码中发现的而言,这确实没有普遍正确的答案,除非您想使用 JNI 调用创建自己的本机启动器可执行文件,并从本机获取当前工作目录启动时的启动器代码。其他一切都至少会有一些细微差别,在某些情况下可能会破裂。
【讨论】:
这在很久以前是正确的(当这个 Q 发布时),但微软不鼓励应用程序更改 system32,并且至少从 2015 年开始,Oracle Windows 安装程序将他们的存根放在\programdata\Oracle\Java\javapath
或 \Program Files [(x86)]\Common Files\Oracle\Java\javapath
as MS批准【参考方案8】:
当混乱的时刻冒出来时,这是我的灵丹妙药。(把它称为主要的第一件事)。也许例如 JVM 被 IDE 滑入不同的版本。此静态函数搜索当前进程 PID 并在该 pid 上打开 VisualVM。混乱就停在那里,因为你想要它并且你得到它......
public static void callJVisualVM()
System.out.println("USER:DIR!:" + System.getProperty("user.dir"));
//next search current jdk/jre
String 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();
【讨论】:
你应该写一本关于这个问题的书。这 50 行代码还不够。【参考方案9】:这将为您提供当前工作目录的路径:
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();
【讨论】:
这只是返回 '.'对我来说。 是的,在许多系统中这将是对工作目录的引用。要获取绝对路径,您可以再添加一个方法调用Path path = FileSystems.getDefault().getPath(".").toAbsolutePath();
你不需要foo.txt,只需输入一个空字符串即可获取目录
在 Windows (10) 上,这只是给了我一个 Path
对象,指向当前工作目录中名为 .
的文件。使用空字符串,而不是 "."
对我有用。【参考方案10】:
当前工作目录在不同的 Java 实现中定义不同。对于 Java 7 之前的某些版本,没有一致的方法来获取工作目录。您可以通过使用 -D
启动 Java 文件并定义一个变量来保存信息来解决此问题
类似
java -D com.mycompany.workingDir="%0"
这不太对,但你明白了。然后System.getProperty("com.mycompany.workingDir")
...
【讨论】:
与问题无关。 它确实对 Java 有意义 - 它是您使用相对路径名打开的文件在磁盘上的相对位置。 是的,它是有含义的。我的话选得有点差。但是你错过了重点——在 Java 7 之前,没有办法知道当前的工作目录,并且不同的实现设置它们......不同......【参考方案11】:提到它仅在 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[*** user] + bachden [*** user]
*/
public static final String getBasePathForClass(Class<?> classs)
// Local variables
File file;
String basePath = "";
boolean failed = false;
// Let's give a first try
try
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 eclipse
if (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 netbeans
if (basePath.endsWith(File.separator + "build" + File.separator + "classes"))
basePath = basePath.substring(0, basePath.length() - 14);
// end fix
if (!basePath.endsWith(File.separator))
basePath = basePath + File.separator;
return basePath;
【讨论】:
这将返回 JAR 文件的位置。不是所要求的。 @EJP .jar文件所在的位置不是java程序的当前工作目录?【参考方案12】:以下适用于 Java 7 及更高版本(有关文档,请参阅 here)。
import java.nio.file.Paths;
Paths.get(".").toAbsolutePath().normalize().toString();
【讨论】:
这比更便携的import java.io.File; File(".").getAbsolutePath()
好在哪里?
当您说可移植时,您的意思是它可以在 Java 6 及更早版本中运行? Paths.get()
可能被认为更好,因为它可以直接访问更强大的Path
接口。
在这种情况下使用.normalize()
的潜在优势是什么?
@OleV.V.来自 Javadoc:(规范化方法)Returns a path that is this path with redundant name elements eliminated.
【参考方案13】:
是什么让您认为 c:\windows\system32 不是您的当前目录? user.dir
属性明确为“用户的当前工作目录”。
换句话说,除非您从命令行启动 Java,否则 c:\windows\system32 可能是您的 CWD。也就是说,如果您双击启动程序,则 CWD 不太可能是您从中双击的目录。
编辑:这似乎只适用于旧 Windows 和/或 Java 版本。
【讨论】:
这似乎不是真的,至少在我使用 Java 7 的 Windows 7 机器上不是这样。user.dir
始终是我双击 jar 文件的文件夹。【参考方案14】:
使用CodeSource#getLocation()
。
这在 JAR 文件中也可以正常工作。您可以通过ProtectionDomain#getCodeSource()
获得CodeSource
,而ProtectionDomain
又可以通过Class#getProtectionDomain()
获得。
public class Test
public static void main(String... args) throws Exception
URL location = Test.class.getProtectionDomain().getCodeSource().getLocation();
System.out.println(location.getFile());
【讨论】:
这将返回 JAR 文件的位置。不是所要求的。【参考方案15】:使用 Windows user.dir 会按预期返回目录,但不是在您以提升的权限启动应用程序时(以管理员身份运行),在这种情况下您会得到 C:\WINDOWS\system32
【讨论】:
【参考方案16】:在 Linux 上,当您从 终端 运行 jar 文件时,它们都将返回相同的 String
:"/home/CurrentUser",不管你的 jar 文件在哪里。这仅取决于您在启动 jar 文件时在终端上使用的当前目录。
Paths.get("").toAbsolutePath().toString();
System.getProperty("user.dir");
如果你的Class
和main
会被称为MainClass
,那么试试:
MainClass.class.getProtectionDomain().getCodeSource().getLocation().getFile();
这将返回一个带有 jar 文件的绝对路径的String
。
【讨论】:
这不是所要求的。 这个答案不能按字面意思理解。【参考方案17】:假设您正在尝试在 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 eclipse
if (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 netbean
if (basePath.endsWith(File.separator + "build" + File.separator + "classes"))
basePath = basePath.substring(0, basePath.length() - 14);
// end fix
if (!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
最好的,
【讨论】:
这将返回 JAR 文件的位置。不是所要求的。 @user207421 是的,我知道这个答案不是问题的真正答案,但大多数时候,每个人都希望获得“jar 所在的目录”而不是“命令行工作目录”。 【参考方案18】:此处发布的所有答案均不适合我。以下是有效的方法:
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()
【讨论】:
这将返回 JAR 文件的位置。不是所要求的。【参考方案19】:通常,作为文件对象:
File getCwd()
return new File("").getAbsoluteFile();
您可能希望拥有像 "D:/a/b/c" 这样的完整限定字符串:
getCwd().getAbsolutePath()
【讨论】:
这在 android 测试中效果很好,因为 Android 不包含 java.nio.file.Files。 在静态上下文中似乎对我不起作用(new File("") throws NullPointerException)..? @nsandersen 您可能使用了错误的文件对象:System.out.println(new java.io.File("").getAbsolutePath());【参考方案20】:System.getProperty("java.class.path")
【讨论】:
【参考方案21】:我在 Linux 上使用这两种方法得到相同的结果:
@Test
public void aaa()
System.err.println(Paths.get("").toAbsolutePath().toString());
System.err.println(System.getProperty("user.dir"));
Paths.get("")
docs
System.getProperty("user.dir")
docs
【讨论】:
【参考方案22】:我希望你想访问包含包的当前目录,即如果你的 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);
注意:此代码仅在 Windows 中使用 Oracle JRE 进行测试。
【讨论】:
不反对这个答案是有害的。发帖前请三思。你的代码坏了,除非所有这些都是真的: 1. JRE 是 Oracle 的,否则将没有“sun.java.command”系统属性→NPE; 2.操作系统是Windows(使用File.separator
代替,或多参数File
构造函数); 3. 命令行中指定了类路径,和 '当前目录包括包'(??) 是:首先指定,b。绝对指定,c。与 CWD 完全匹配(即使 Windows 不区分大小写),并且 d.是 CWD 的后代
解决了第 1 点和第 2 点。但除非我遗漏了什么,否则您仍然依赖于在命令行中指定的类路径(即不在环境变量中),并且对于 '当前目录,包括包'(我承认我不太明白你的意思)是类路径中第一个元素的后代。并且大小写匹配问题仍然存在。如果我的评论没有帮助,我很抱歉;我牺牲了清晰度以保持在评论字符限制内。
@Inversus,它只在某些环境中“完美运行”;你只是碰巧有幸以这样的方式测试它。编写在合法运行时环境中失败的软件并不是一个好的做法,即使您的测试环境集不够广泛,无法包含它们。
@CharlesDuffy 你是对的,这不是一个好习惯。幸运的是,这个解决方案“解决了我的特定问题”并没有导致它“在合法的运行时环境中失败”。事实上,它帮助我解决了这样的失败并编写了更健壮的代码,除了解决我遇到的非常具体的问题(这只是与这个问题/答案有点相关)。我想我很幸运能找到它。【参考方案23】:
这就是我的解决方案
File currentDir = new File("");
【讨论】:
当您使用这样的 File 对象作为另一个 File 的父级时,这会产生副作用:new File(new File(""), "subdir") 将无法按预期工作 要解决这个问题,请改用new File("").getAbsoluteFile()
。
对于它的价值,我最好用 File(".")。
How To Define a Relative Path in Java 这个页面帮助了我。我还假设在创建相对路径时应该使用/
。我错了,不要以/
开头。 ../
也适用于在目录树中向上。
@keshlam 这给了我当前目录中一个名为 .
的文件。【参考方案24】:
this.getClass().getClassLoader().getResource("").getPath()
【讨论】:
当我通过双击从 JAR 文件启动我的应用程序时引发 NPE。 如果应用程序从 JAR 文件或 CLASSPATH 元素运行,则返回""
。不是所要求的。
@Zizouz212 getClass()
是一种对象方法,因此在静态上下文中仅删除 this
是行不通的。您必须通过 MyClass.class.getClassLoader().....
明确引用您所在的课程。以上是关于如何在 Java 中获取当前工作目录?的主要内容,如果未能解决你的问题,请参考以下文章
如何在 Objective-C 中获取当前工作目录的绝对路径?