在Java中改变当前的工作目录?

如何从Java程序中更改当前的工作目录? 我所能find的关于这个问题的一切都表明你根本做不到,但是我不能相信那是真的。

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

我会明白,如果Java不允许你这样做,如果它不允许你得到当前的工作目录,甚至允许你使用相对文件path打开文件….

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

File(String parent, String child)构造函数可以帮助,如果你build立你的目录path与文件path分开,允许更容易的交换。

另一种方法是设置一个脚本来从其他目录运行Java,或者使用JNI本机代码,如下所示 。

相关的Sun bug在2008年被closures为“不会修复”。

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

有一种方法可以使用系统属性“user.dir”来做到这一点。 要理解的关键是getAbsoluteFile()必须被调用(如下所示),否则相对path将被parsing为默认的 “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"); } } 

可以使用JNA / JNI来调用libc来更改PWD。 JRuby的人有一个方便的Java库进行POSIX调用称为jna-posix这是maven信息

你可以在这里看到一个例子(Clojure代码,对不起)。 看看函数chdirToRoot

如果我理解正确,Java程序将以当前环境variables的副本开始。 通过System.setProperty(String, String)进行的任何更改都会修改副本,而不是原始的环境variables。 这并不是说为什么Sunselect这种行为提供了一个彻底的理由,但也许它有点点亮…

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

请参阅Runtime.exec javadocs

特别,

 public Process exec(String[] cmdarray,String[] envp, File dir) throws IOException 

其中dir是运行subprocess的工作目录

工作目录是一个操作系统function(在进程启动时设置)。 为什么不传递自己的系统属性( -Dsomeprop=/my/path ),并将其作为你的文件的父代:

 File f = new File ( System.getProperty("someprop"), myFilename) 

在这里做的更聪明/容易的事情就是改变你的代码,而不是打开文件假设它存在于当前的工作目录(我假设你正在做一些像new File("blah.txt") ,只是build立自己的文件path。

让用户通过基本目录,从configuration文件中读取它,如果其他属性找不到,则返回到user.dir等等。但是改善程序中的逻辑比改变它更容易改变环境variables的工作方式。

我试图调用

String oldDir = System.setProperty("user.dir", currdir.getAbsolutePath());

这似乎工作。 但

File myFile = new File("localpath.ext"); InputStream openit = new FileInputStream(myFile);

抛出一个FileNotFoundException虽然

myFile.getAbsolutePath()

显示正确的path。 我读过这个 。 我认为问题是:

  • Java使用新设置知道当前目录。
  • 但是文件处理是由操作系统完成的。 不幸的是,它不知道新设置的当前目录。

解决scheme可能是:

File myFile = new File(System.getPropety("user.dir"), "localpath.ext");

它以JVM所知的当前目录创build一个绝对的文件对象。 但是这个代码应该存在于一个使用的类中,它需要改变重用的代码。

~~~~ JcHartmut

对这个问题的其他可能的答案可能取决于你打开文件的原因。 这是属性文件还是与您的应用程序有一些configuration相关的文件?

如果是这种情况,你可以考虑通过类path加载器来加载文件,这样你就可以加载Java可以访问的任何文件。

如果你在一个shell中运行你的命令,你可以写下类似“java -cp”的命令,并添加你想用“:”隔开的任何目录,如果java没有在一个目录中find某个目录,它将尝试在其他目录中find它们就是我所做的

您可以使用

新文件(“相对/path”)。getAbsoluteFile()

System.setProperty(“user.dir”,“/ some / directory”)

 System.setProperty("user.dir", "C:/OtherProject"); File file = new File("data/data.csv").getAbsoluteFile(); System.out.println(file.getPath()); 

将打印

 C:\OtherProject\data\data.csv 

使用FileSystemView

 private FileSystemView fileSystemView; fileSystemView = FileSystemView.getFileSystemView(); currentDirectory = new File("."); //listing currentDirectory File[] filesAndDirs = fileSystemView.getFiles(currentDirectory, false); fileList = new ArrayList<File>(); dirList = new ArrayList<File>(); for (File file : filesAndDirs) { if (file.isDirectory()) dirList.add(file); else fileList.add(file); } Collections.sort(dirList); if (!fileSystemView.isFileSystemRoot(currentDirectory)) dirList.add(0, new File("..")); Collections.sort(fileList); //change currentDirectory = fileSystemView.getParentDirectory(currentDirectory);