I'm running into a pesky little error and I'm not sure how to solve it. What I'm trying to do is pretty simple: Run an external .java file using ProcessBuilder. Just like that tittle suggests.
The problem is that the file that runs and creates this ProcessBuilder is in a different directory than the other file I want to run.
What I'm trying to do to get around this is:
String command[] = {"javac",JAVA_FILE_LOCATION};
ProcessBuilder processBuilder = new ProcessBuilder("cd");
Process process0 = processBuilder.start();
to reset the directory and
processBuilder = new ProcessBuilder(command);
Process process = processBuilder.start();
to compile the other file
if( process.getErrorStream().read() != -1 ){
print("Compilation Errors",process.getErrorStream());
}
and just some error handling here. However it doesn't get past this error handle part. I can't figure out the proper way of doing this. Here's the error message:
my_PC:Processes user$ java -jar process.jar
************* Compilation Errors***********************
avac: file not found: /Users/Desktop/Piano.java
Usage: javac <options> <source files>
use -help for a list of possible options
Exception in thread "main" java.lang.IllegalThreadStateException: process hasn't exited
at java.lang.UNIXProcess.exitValue(UNIXProcess.java:423)
at my.package.address.Main.main(Main.java:28)
Does anyone know what I'm doing wrong ? Also I can post the whole code if needed, but I figured it's not really relevant here.
UPDATED: added my code
package some.random.package;
import java.io.*;
public class Main {
/**
* Provide absolute JAVA file path
*/
private static final String JAVA_FILE_LOCATION = "/Users/Desktop/piano.java";
public static void main(String args[]) throws IOException
{
String command[] = {"javac",JAVA_FILE_LOCATION};
ProcessBuilder processBuilder = new ProcessBuilder(command).directory(new File("/Users/Desktop/"));
Process process = processBuilder.start();
if( process.getErrorStream().read() != -1 ){
print("Compilation Errors",process.getErrorStream());
}
/**
* check if compile is successful
* 0 => successful
*/
if( process.exitValue() == 0 )
{
process = new ProcessBuilder(new String[]{"java","piano"}).directory(new File("/Users/Desktop/")).start();
if( process.getErrorStream().read() != -1 )
print("Errors ",process.getErrorStream());
else
print("Output ",process.getInputStream());
/**
* Check if RuntimeException or Errors encounter during execution then print errors on console
* Otherwise print Output
*/
}
}
private static void print(String status,InputStream input) throws IOException
{
BufferedReader in = new BufferedReader(new InputStreamReader(input));
System.out.println("************* "+status+"***********************");
String line = null;
while((line = in.readLine()) != null ){
System.out.println(line);
}
in.close();
}
}
The cd
command you execute with the first ProcessBuilder
affects only that child process, it does not change the working directory of the main executing program.
When you run the second ProcessBuilder
, it will have the working directory as the main program,
completely unaffected by the cd
executed by the previous ProcessBuilder
.
To execute a program from a different directory, use the directory(...)
method of ProcessBuilder
:
String command[] = {"javac", JAVA_FILE_LOCATION};
ProcessBuilder processBuilder = new ProcessBuilder(command).directory(new File("path/to/dir"));
Process process0 = processBuilder.start();
Btw, the path "/Users/Desktop/piano.java" looks very strange.
The path to a user's desktop on a Mac is usually /Users/username/Desktop
,
so the path in your code implies that your username is "Desktop",
which is very unusual.
And, to make it easier to work with the program,
I suggest to put the base directory path (/Users/username/Desktop
) in a variable,
rather then hardcoding it at multiple places.
That way it will be easier to make changes, no need to edit at multiple places.