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

120

假设我的主类在 C:\Users\Justian\Documents\,如何让程序显示它在 C:\Users\Justian\Documents 中?

硬编码不是选项——如果将其移动到其他位置,它需要是可适应的。

我想把一堆CSV文件放在一个文件夹中,让程序识别所有文件,然后加载数据并操作它们。我只想知道如何导航到那个文件夹。


1
请查看此文章:http://www.roseindia.net/java/java-get-example/get-class-location.shtml。 - Matthew J Morrison
1
如果你的主类在一个jar文件中,那么你想要什么样的结果呢? - Mattias Nilsson
1
你为什么需要这样做呢? - Ed S.
1
听起来你需要的是CSV文件所在的目录,并且让.jar文件能够引用该目录。如果是这种情况,请参考我的答案。 - user177800
@MatthewJMorrison,出故障了。 - Paul Draper
显示剩余2条评论
8个回答

160
一种方法是使用系统属性System.getProperty("user.dir");,这将给出“初始化属性时的当前工作目录”。这可能是您想要的。要找出在哪个目录中发出了java命令,在您的情况下是在要处理的文件所在的目录中,即使实际的.jar文件可能存储在机器上的其他位置。在大多数情况下,拥有实际.jar文件的目录并不那么有用。
以下内容将从调用命令的当前目录打印出当前目录,而不管.class或.jar文件中的.class文件位于何处。
public class Test
{
    public static void main(final String[] args)
    {
        final String dir = System.getProperty("user.dir");
        System.out.println("current dir = " + dir);
    }
}  

如果您在/User/me/中,包含上述代码的.jar文件位于/opt/some/nested/dir/中,则命令java -jar /opt/some/nested/dir/test.jar Test将输出current dir = /User/me

作为奖励,您还应该考虑使用一个良好的面向对象的命令行参数解析器。我强烈推荐JSAP,Java Simple Argument Parser。这将让您使用System.getProperty("user.dir"),并且可以传入其他内容以覆盖默认行为。这是一种更可维护的解决方案。这将使传递要处理的目录变得非常容易,并且能够回退到user.dir,如果没有传入任何内容。


我会在有时间的时候测试一下。我现在非常忙于那个.jar文件的问题 :P - Justian Meyer
你有没有访问我在回答中提供的链接,解决那个.jar文件的问题?我展示了如何使用ANT构建.jar文件。 - user177800
Jarrod编写的代码可以轻松地返回System Property user.dir中当前工作目录的绝对路径,非常易于使用。只需调用System.getProperty("user.dir")即可。 - user2916050

80

使用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());
    }
}

根据OP的评论更新:

我想把一堆CSV文件倒入一个文件夹中,让程序识别所有文件,然后加载数据并对其进行操作。我只是想知道如何导航到那个文件夹。

这需要在程序中硬编码/知道它们的相对路径。相反地,考虑将其路径添加到类路径中,以便您可以使用 ClassLoader#getResource()

File classpathRoot = new File(classLoader.getResource("").getPath());
File[] csvFiles = classpathRoot.listFiles(new FilenameFilter() {
    @Override public boolean accept(File dir, String name) {
        return name.endsWith(".csv");
    }
});

或者将其路径作为main()参数传递。


3
实现这一功能需要满足几个条件,其中最重要的是你的“主类”必须从文件系统中加载。在Java中,这种假设被证明并不罕见。但是,如果你确信你是从文件系统上的JAR包中加载你的类,那么这就是可行的方法。 - erickson
请问您能否添加与url类相关的导入吗?网络上有太多的url类,很难找到正确的一个。 - Moebius
@BalusC 那么URL类不是标准类,而是由用户创建的吗? - Moebius
1
@Moebius:嗯?你是新手Java吗?查看javadoc。只需使用由getLocation()方法返回的那个即可。其他的显然不会起作用。 - BalusC
BalusC,你使用的在类名和方法名之间加“#”号的约定是什么?谢谢。 - Sabuncu
显示剩余12条评论

32
File currentDirectory = new File(new File(".").getAbsolutePath());
System.out.println(currentDirectory.getCanonicalPath());
System.out.println(currentDirectory.getAbsolutePath());

输出类似于:

/path/to/current/directory
/path/to/current/directory/.
请注意,File.getCanonicalPath() 方法会抛出受检的 IOException 异常,但它可以移除例如 ../../../ 这样的内容。

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

请注意,这将返回到“bin/classes/”路径,而不仅仅是“bin”。 - android developer
在使用Intellij Idea调试正在运行的应用程序时,返回了"/C:/Program%20Files/Java/jdk1.8.0_112/:"。 - velocity

7
如果您想获取当前工作目录,请使用以下代码行
System.out.println(new File("").getAbsolutePath());

6

我刚刚使用了:

import java.nio.file.Path;
import java.nio.file.Paths;

...

Path workingDirectory=Paths.get(".").toAbsolutePath();

9
你的代码运行不了,正确的应该是 Paths.get("").toAbsolutePath() - To Kra
@ToKra 如果我执行 Paths.get("my/file").toAbsolutePath(),我会得到 /my/file,这绝对不是当前工作目录。 - abergmeier
1
@abergmeier 我写的是"",不是"my/file"。 - To Kra

5
如果你想要获取当前源代码的绝对路径,我的建议是:
String internalPath = this.getClass().getName().replace(".", File.separator);
String externalPath = System.getProperty("user.dir")+File.separator+"src";
String workDir = externalPath+File.separator+internalPath.substring(0, internalPath.lastIndexOf(File.separator));

当您在IDE上运行它或使用某些东西旋转实例时,这将无法正常工作。 - Sarp Kaya
内部路径是 java\lang\Class 外部路径是 E:\BranchProduction1.4.0\FilesTestProject\src 工作目录是 E:\BranchProduction1.4.0\FilesTestProject\src\java\lang,请解释输出的含义。 - JAVA

3

谁说你的主类一定在本地硬盘上的一个文件中?类通常被打包在JAR文件中,有时通过网络加载甚至动态生成。

那么你真正想要做什么?可能有一种方法可以做到这一点,而不会对类的来源作出假设。


我想把一堆CSV文件倒入一个文件夹中,让程序识别所有文件,然后加载数据并操作它们。我真的只想知道如何导航到那个文件夹。 - Justian Meyer
也许我漏掉了什么,但绝对路径似乎可以解决问题。你说你不能硬编码它,但是你怎么知道要从哪个文件夹开始查找呢? - Chris Thompson
问题在于我想将它带到其他计算机上,而不仅仅是我的计算机。我不知道硬编码路径会有多难。"假设我的jar和文件夹总是有类似的关系(即在同一个目录中)。如果是这样,我可以获取jar的目录,然后修改它以找到文件夹。" 我唯一能硬编码的方式就是如果我不必包含从硬盘到文件的完整路径。也许我只能返回3个文件夹(即“文档\项目\转储\[文件/文件夹]”)。 - Justian Meyer
我认为你想要做的是获取JAR文件所在目录的句柄。这样能够满足你的需求吗? - Chris Thompson

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接