在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);