How can I change the current working directory from within a Java program? Everything I've been able to find about the issue claims that you simply can't do it, but I can't believe that that's really the case.
I have a piece of code that opens a file using a hard-coded relative file path from the directory it's normally started in, and I just want to be able to use that code from within a different Java program without having to start it from within a particular directory. It seems like you should just be able to call System.setProperty( "user.dir", "/path/to/dir" ), but as far as I can figure out, calling that line just silently fails and does nothing.
I would understand if Java didn't allow you to do this, if it weren't for the fact that it allows you to get the current working directory, and even allows you to open files using relative file paths....
There is no reliable way to do this in pure Java. Setting the user.dir property via System.setProperty() or java -Duser.dir=... does seem to affect subsequent creations of Files, but not e.g. FileOutputStreams.
The File(String parent, String child) constructor can help if you build up your directory path separately from your file path, allowing easier swapping.
An alternative is to set up a script to run Java from a different directory, or use JNI native code as suggested below.
The relevant OpenJDK bug was closed in 2008 as "will not fix".
If you run your legacy program with ProcessBuilder, you will be able to specify its working directory.
There is a way to do this using the system property "user.dir". The key part to understand is that getAbsoluteFile() must be called (as shown below) or else relative paths will be resolved against the default "user.dir" value.
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");
}
}
It is possible to change the PWD, using JNA/JNI to make calls to libc. The JRuby guys have a handy java library for making POSIX calls called jnr-posix. Here's the maven info
As mentioned you can't change the CWD of the JVM but if you were to launch another process using Runtime.exec() you can use the overloaded method that lets you specify the working directory. This is not really for running your Java program in another directory but for many cases when one needs to launch another program like a Perl script for example, you can specify the working directory of that script while leaving the working dir of the JVM unchanged.
See Runtime.exec javadocs
Specifically,
public Process exec(String[] cmdarray,String[] envp, File dir) throws IOException
where dir is the working directory to run the subprocess in
If I understand correctly, a Java program starts with a copy of the current environment variables. Any changes via System.setProperty(String, String) are modifying the copy, not the original environment variables. Not that this provides a thorough reason as to why Sun chose this behavior, but perhaps it sheds a little light...
The working directory is a operating system feature (set when the process starts).
Why don't you just pass your own System property (-Dsomeprop=/my/path) and use that in your code as the parent of your File:
File f = new File ( System.getProperty("someprop"), myFilename)
The smarter/easier thing to do here is to just change your code so that instead of opening the file assuming that it exists in the current working directory (I assume you are doing something like new File("blah.txt"), just build the path to the file yourself.
Let the user pass in the base directory, read it from a config file, fall back to user.dir if the other properties can't be found, etc. But it's a whole lot easier to improve the logic in your program than it is to change how environment variables work.
I have tried to invoke
String oldDir = System.setProperty("user.dir", currdir.getAbsolutePath());
It seems to work. But
File myFile = new File("localpath.ext");
InputStream openit = new FileInputStream(myFile);
throws a FileNotFoundException though
myFile.getAbsolutePath()
shows the correct path.
I have read this. I think the problem is:
Java knows the current directory with the new setting.
But the file handling is done by the operation system. It does not know the new set current directory, unfortunately.
The solution may be:
File myFile = new File(System.getPropety("user.dir"), "localpath.ext");
It creates a file Object as absolute one with the current directory which is known by the JVM. But that code should be existing in a used class, it needs changing of reused codes.
~~~~JcHartmut
You can use
new File("relative/path").getAbsoluteFile()
after
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());
Will print
C:\OtherProject\data\data.csv
You can change the process's actual working directory using JNI or JNA.
With JNI, you can use native functions to set the directory. The POSIX method is chdir(). On Windows, you can use SetCurrentDirectory().
With JNA, you can wrap the native functions in Java binders.
For Windows:
private static interface MyKernel32 extends Library {
public MyKernel32 INSTANCE = (MyKernel32) Native.loadLibrary("Kernel32", MyKernel32.class);
/** BOOL SetCurrentDirectory( LPCTSTR lpPathName ); */
int SetCurrentDirectoryW(char[] pathName);
}
For POSIX systems:
private interface MyCLibrary extends Library {
MyCLibrary INSTANCE = (MyCLibrary) Native.loadLibrary("c", MyCLibrary.class);
/** int chdir(const char *path); */
int chdir( String path );
}
The other possible answer to this question may depend on the reason you are opening the file. Is this a property file or a file that has some configuration related to your application?
If this is the case you may consider trying to load the file through the classpath loader, this way you can load any file Java has access to.
If you run your commands in a shell you can write something like "java -cp" and add any directories you want separated by ":" if java doesnt find something in one directory it will go try and find them in the other directories, that is what I do.
Use 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);
I have a program which replaces text in a file based on command line input. Currently it creates a temporary file, and writes the string with the replaced text in the new temporary file. This program works on a desktop in a computer lab on my campus, but when I try to run it on my personal laptop, the temporary file is created, I can find it by printing its canonical path, and file.exists() returns true, but it does not show up on my desktop.
A search using Windows Explorer yields nothing.
I am running Windows 7 and using TextPad. Does anyone know what might be causing this? I can supply any other necessary information.
Edit: I am running Windows 7 on a Mac Pro 2011, if that makes any difference at all.
Edit: I discovered the problem. I had downloaded Comodo Antivirus software and whenever I created a file it would create it in a VTRoot folder for sandbox purposes. I was able to alter the settings and solved my issue.
import java.io.*;
import java.util.*;
public class ReplaceText{
public static void main(String[] args)throws IOException{
if(args.length != 2){
System.out.println("Incorrect format. Use java ClassName textToReplace filename");
System.exit(1);
}
File source = new File(args[1]);
if(!source.exists()){
System.out.println("Source file " + args[1] + " does not exist.");
System.exit(2);
}
File temp = new File("temp.txt");
try(
Scanner input = new Scanner(source);
PrintWriter output = new PrintWriter(temp);
){
while(input.hasNext()){
String s1 = input.nextLine();
String s2 = s1.replace(args[0], "a");
output.println(s2);
}
}
}
}
If you could not see the temp.txt file it is because it is located in your project directory where your java source code are located.However if you will found it then also it will contain nothing.The reason being you have not closed the output stream to file just place
output.close()
after the while loop.
Try to create file by providing entire file path while creating like
File(URI uri)
This creates a new File instance by converting the given file: URI into an abstract pathname.
I discovered the problem. I had downloaded Comodo Antivirus software and whenever I created a file it would create it in a VTRoot folder for sandbox purposes. I was able to alter the settings and solved my issue.
If you have installed comodo antivirus then you should follow the instruction :
1.Open the comodo,
2.Click on the settings,
3.Then click on the Containment -> click on the Auto-containment,
4.Then at the top, uncheck the enable auto-containment.
I need that my program would support the operation :
java -jar filename.jar < input3.txt
I don't realy know how to deal with such command. How can I read the input file in my main program?
I need to read the txt file line by line.
You have the answer for your question in this post.
The main method of your program has to be ready to accept the file path in its arguments (and do what it has to do with the file).
If the file path is the first argument, then you can access it through the first position of the arguments array.
public class MainClass {
public static void main(String[] args) {
String filePath = args[0];
}
}
To execute, you'll just have to do:
java -jar filename.jar input3.txt
I found a solution, i used the command
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
for the input
I'm trying to connect a Java project with a website. The project is located in "website_folder/data/backend" and at that time, I want to test if the following example works:
[java code]
public static void main(string args[]) {
if(args[0].equals("5") {
File f = new File("/location/to/file/result.txt");
if(!f.exists()) {
f.createNewFile();
FileWriter fstream = new FileWriter("/location/to/file/result.txt");
BufferedWriter out = new BufferedWriter(fstream);
out.write("It works!");
out.close();
}
}
}
And in the PHP file I have to following command:
<?php
exec("java -cp /data/backend/Project/build/classes/project/Main.class/ main 5",$output);
?>
but nothing happens! I mean, the file isn't created in the directory I have specified in the main method. I have tried to run the .jar file of the project in the PHP command, to pass the argument "5" via a variable, to add to the directory path -in the exec command- this: "i:/xampp/htdocs/website_folder/" (I:\ is the disk drive where I have my virtual server -xampp- installed), but in vain. Am I doing something wrong with the syntax of the command?
Edit:
I changed the command to point the .jar file (java -jar /data/backend/Project/dist/Project.jar 5) and the problem is solved.
Try this:
"java -cp /data/backend/Project/build/classes/ project.Main 5"
This assumes, that the class which contains your main method is in package project and is called Main. If this is not the case, adapt accordingly.
I am making a program that opens and reads a file.
This is my code:
import java.io.*;
public class FileRead{
public static void main(String[] args){
try{
File file = new File("hello.txt");
System.out.println(file.getCanonicalPath());
FileInputStream ft = new FileInputStream(file);
DataInputStream in = new DataInputStream(ft);
BufferedReader br = new BufferedReader(new InputStreamReader(in));
String strline;
while((strline = br.readLine()) != null){
System.out.println(strline);
}
in.close();
}catch(Exception e){
System.err.println("Error: " + e.getMessage());
}
}
}
but when I run, I get this error:
C:\Users\User\Documents\Workspace\FileRead\hello.txt
Error: hello.txt (The system cannot find the file specified)
my FileRead.java and hello.txt where in the same directory that can be found in:
C:\Users\User\Documents\Workspace\FileRead
I'm wondering what I am doing wrong?
Try to list all files' names in the directory by calling:
File file = new File(".");
for(String fileNames : file.list()) System.out.println(fileNames);
and see if you will find your files in the list.
I have copied your code and it runs fine.
I suspect you are simply having some problem in the actual file name of hello.txt, or you are running in a wrong directory. Consider verifying by the method suggested by #Eng.Fouad
You need to give the absolute pathname to where the file exists.
File file = new File("C:\\Users\\User\\Documents\\Workspace\\FileRead\\hello.txt");
In your IDE right click on the file you want to read and choose "copy path"
then paste it into your code.
Note that windows hides the file extension so if you create a text file "myfile.txt" it might be actually saved as "myfile.txt.txt"
Generally, just stating the name of file inside the File constructor means that the file is located in the same directory as the java file. However, when using IDEs like NetBeans and Eclipse i.e. not the case you have to save the file in the project folder directory. So I think checking that will solve your problem.
How are you running the program?
It's not the java file that is being ran but rather the .class file that is created by compiling the java code. You will either need to specify the absolute path like user1420750 says or a relative path to your System.getProperty("user.dir") directory. This should be the working directory or the directory you ran the java command from.
First Create folder same as path which you Specified. after then create File
File dir = new File("C:\\USER\\Semple_file\\");
File file = new File("C:\\USER\\Semple_file\\abc.txt");
if(!file.exists())
{
dir.mkdir();
file.createNewFile();
System.out.println("File,Folder Created.);
}
When you run a jar, your Main class itself becomes args[0] and your filename comes immediately after.
I had the same issue: I could locate my file when provided the absolute path from eclipse (because I was referring to the file as args[0]). Yet when I run the same from jar, it was trying to locate my main class - which is when I got the idea that I should be reading my file from args[1].