在Java中更改当前工作目录?

Nic*_*ick 164 java working-directory

如何在Java程序中更改当前工作目录?我能找到的关于这个问题的一切声称你根本做不到,但我不相信那是真的.

我有一段代码,它使用来自通常启动的目录的硬编码相对文件路径打开文件,我只是希望能够在不同的Java程序中使用该代码,而无需从内部启动它一个特定的目录.看起来你应该只能调用System.setProperty( "user.dir", "/path/to/dir" ),但据我所知,调用该行只是默默地失败并且什么都不做.

我会理解,如果Java不允许你这样做,如果它不是因为它允许你获得当前的工作目录,甚至允许你使用相对文件路径打开文件....

Mic*_*ers 143

在纯Java中没有可靠的方法来做到这一点.user.dir通过System.setProperty()java -Duser.dir=...似乎影响后续创作的属性Files,但不是例如FileOutputStreams.

File(String parent, String child)构造可以帮助您从您的文件路径单独建立你的目录路径,用户可以方便地交换.

另一种方法是设置脚本以从其他目录运行Java,或者使用下面建议的 JNI本机代码.

相关的Sun漏洞在2008年被关闭,因为"无法修复".

  • 我不认为我发现java和c#之间的一个区别让我觉得,"那些java家伙肯定知道他们在做什么" (11认同)
  • 看起来有一种方法:http://stackoverflow.com/a/8204584/104021 (9认同)
  • 在Java的防御中(我是一个需要此功能的UNIX人员)......它是一个与操作系统细节无关的虚拟机.某些操作系统中不提供"当前工作目录"习惯用法. (5认同)
  • 为了公平对待Java,他们必须首先做到这一点,C#的好处是能够从许多方面的错误中吸取教训. (4认同)
  • @VolkerSeibt:在进一步调查中,似乎user.dir仅适用于某些类,包括我最初测试过的类.`new FileOutputStream("foo.txt").close();`即使user.dir被程序更改,`也会在原始工作目录中创建文件. (3认同)
  • 你是对的,即使在Java 8和9中它也是错误的. (3认同)
  • 很难相信java没有一些参数"在这个目录中开始......"至少...... (2认同)

Phi*_*Lho 37

如果使用ProcessBuilder运行旧程序,则可以指定其工作目录.


Ste*_*e K 29

这里一个办法做到这一点使用系统属性"user.dir来".要理解的关键部分是必须调用getAbsoluteFile()(如下所示),否则将根据默认的 "user.dir"值解析相对路径.

import java.io.*;

public class FileUtils
{
    public static boolean setCurrentDirectory(String directory_name)
    {
        boolean result = false;  // Boolean indicating whether directory was set
        File    directory;       // Desired current working directory

        directory = new File(directory_name).getAbsoluteFile();
        if (directory.exists() || directory.mkdirs())
        {
            result = (System.setProperty("user.dir", directory.getAbsolutePath()) != null);
        }

        return result;
    }

    public static PrintWriter openOutputFile(String file_name)
    {
        PrintWriter output = null;  // File to open for writing

        try
        {
            output = new PrintWriter(new File(file_name).getAbsoluteFile());
        }
        catch (Exception exception) {}

        return output;
    }

    public static void main(String[] args) throws Exception
    {
        FileUtils.openOutputFile("DefaultDirectoryFile.txt");
        FileUtils.setCurrentDirectory("NewCurrentDirectory");
        FileUtils.openOutputFile("CurrentDirectoryFile.txt");
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 绝对路径至关重要 (3认同)
  • 但它不会更改当前的工作目录.只有`user.dir`的值.绝对路径变得至关重要的事实证明了这一点. (3认同)

All*_*ner 17

可以使用JNA/JNI来调用libc来更改PWD.JRuby的人有一个方便的java库,用于调用POSIX调用jna-posix这里是maven信息

你可以在这里看到它的使用示例(Clojure代码,对不起).查看函数chdirToRoot

  • 似乎没有 jna-posix 的现代版本。我分叉并添加了一个:http://github.com/pbiggar/jnr-posix。我可以确认我可以用这个更改 PWD。 (2认同)
  • 您可以执行此操作,但如果您不更改“user.dir”系统属性,则“File.getAbsolutePath()”将根据“user.dir”进行解析,而“文件”中的路径名将根据操作系统工作目录进行解析。 (2认同)

Ada*_*ter 11

如果我理解正确,Java程序将以当前环境变量的副本开头.任何更改都会System.setProperty(String, String)修改副本,而不是原始环境变量.并不是说这为Sun选择这种行为的原因提供了一个彻底的理由,但也许它有点轻松......

  • 您似乎混淆了环境变量和属性。前者从OS继承而来,后者可以在命令行中使用`-D`进行定义。但是我同意,在JVM上启动预定义的属性(如`user.dir`)会从操作系统中复制,以后再更改它们无济于事。 (2认同)

Biz*_*rck 11

如前所述,您无法更改JVM的CWD,但如果您要使用Runtime.exec()启动另一个进程,则可以使用重载方法来指定工作目录.这不是真正用于在另一个目录中运行Java程序,但是在许多情况下,当需要启动另一个程序(例如Perl脚本)时,您可以指定该脚本的工作目录,同时保持JVM的工作目录不变.

请参见Runtime.exec javadocs

特别,

public Process exec(String[] cmdarray,String[] envp, File dir) throws IOException
Run Code Online (Sandbox Code Playgroud)

在哪里dir运行子进程的工作目录

  • 这似乎是比公认的答案更好的答案(以“在纯 Java 中没有可靠的方法可以做到这一点。”开头)。有没有办法请求将此答案视为已接受的答案? (2认同)

rap*_*aëλ 5

工作目录是操作系统功能(在进程启动时设置).为什么不直接传递自己的System属性(-Dsomeprop=/my/path)并在代码中使用它作为文件的父级:

File f = new File ( System.getProperty("someprop"), myFilename)
Run Code Online (Sandbox Code Playgroud)