I'm working on a chess program in Java. To calculate the best move (when a person plays against the computer) I use a UCI (universal chess interface). That's a Terminal application (I'm using Mac OS X). With Java I want to execute some commands to get the best move. That's what I have up to now:
String[] commands = {"/Users/dejoridavid/Desktop/stockfish-6-64", "isready", "uci"};
Process process = null;
try {
process = Runtime.getRuntime().exec(commands);
} catch (IOException e) {
e.printStackTrace();
}
BufferedReader stdInput = new BufferedReader(new InputStreamReader(process.getInputStream()));
// read the output from the command
String s;
try {
while ((s = stdInput.readLine()) != null) {
System.out.println(s);
}
} catch (IOException e) {
e.printStackTrace();
}
The first command in the array calls the terminal application. The second and third one are both in-app-commands. Now I have one problem. Only the first two commands are executed, their result is printed in the console, the third command is ignored. Did I do something wrong? Please tell me how to also execute the third (or more, 4th, 5th, etc) command.
You can't use Runtime.getRuntime().exec() to execute commands inside another program.
The array you pass to the exec method take the first element of the array as the command and the others as parameters for the command.
From javadoc of public Process exec(String[] cmdarray) throws IOException
Parameters: cmdarray - array containing the command to call and its
arguments.
You have to execute the main command with a call to Runtime.getRuntime().exec()
Then you have to write/read the commands /answers using the inputstream/outputstream of the Process returned by the call to Runtime.getRuntime().exec()
To retrieve inputstream and outputstream of a process use the getInputStream() and getOutputStream() methods on the process object
Related
This question already has answers here:
Java Runtime.getRuntime(): getting output from executing a command line program
(12 answers)
Closed 2 years ago.
I have a standard Maven project and I want to run the meTypeset script. This script takes 3 args where the second one is a file and the third one is a folder created as output.
This is how the script runs in a cmd:
meTypeset.py docx <input> <output_folder> [options]
This is how I try to run it in Java:
public static void main(String args[]) {
String[] cmd = {
"python",
"resources\\pyscripts\\meTypeset.py",
"docx",
"resources\\exampledocs\\example_journal.docx",
"resources\\output"
};
try {
Runtime.getRuntime().exec(cmd);
} catch (IOException e) {
e.printStackTrace();
}
}
Nothing happens, no errors but no result also
Unlike python Java may need some help. Do I guess correctly you are running on Windows?
You invoke the Runtime.exec() method. The method returns a Process instance, and in it's documentation you can read
By default, the created process does not have its own terminal or
console. All its standard I/O (i.e. stdin, stdout, stderr) operations
will be redirected to the parent process, where they can be accessed
via the streams obtained using the methods getOutputStream(),
getInputStream(), and getErrorStream(). The parent process uses these
streams to feed input to and get output from the process. Because some
native platforms only provide limited buffer size for standard input
and output streams, failure to promptly write the input stream or read
the output stream of the process may cause the process to block, or
even deadlock.
So it is likely your process is started by the OS but gets blocked due to I/O restrictions. Get around that by reading the STDOUT and STDERR streams until your process finishes. One good programming model is visible at https://www.baeldung.com/run-shell-command-in-java
#Hiran Chaudhuri explained the error correctly. I am just posting how I solved it, thanks to # Sonnenhut comment.
Runtime rt = Runtime.getRuntime();
String[] commands = {
"python",
"src\\main\\resources/pyscripts/meTypeset.py",
"docx",
"src\\main\\resources/exampledocs/example_journal.docx",
"src\\main\\resources/output"
};
Process proc = rt.exec(commands);
BufferedReader stdInput = new BufferedReader(new
InputStreamReader(proc.getInputStream()));
BufferedReader stdError = new BufferedReader(new
InputStreamReader(proc.getErrorStream()));
// Read the output from the command
System.out.println("Here is the standard output of the command:\n");
String s = null;
while ((s = stdInput.readLine()) != null) {
System.out.println(s);
}
// Read any errors from the attempted command
System.out.println("Here is the standard error of the command (if any):\n");
while ((s = stdError.readLine()) != null) {
System.out.println(s);
}
}
Recently I am trying to write an java application to call SCM.exe to execute the code loading job. However, after I successfully execute the SCM load command via java, I found that I actually cannot really download the code (as using the command line, the password need to be entered after execute the SCM load command). May I know how can I enter this password just after I use the process to run the SCM in java? How can I get the output of the command line and enter something into the command line?
Thanks a million,
Eric
Since I don't know what exactly SCM.exe in your case is, I'm answering only what deals with the input/output redirection requirements in an abstract sense. I assume further that you are calling SCM.exe with whatever parameters it needs through System("...") and this is where you are unable pass any further input (stdin of the called process).
You need, instead, to be able to, upon receiving the request for password, pass it to the stdin of the other process, which is solved by using pipes in the classical sense (since you are presumably on Windows, YMMV). More generally, you are dealing with a very simple case of IPC.
In Java you may find an adequate solution by using ProcessBuilder [1] (never did myself, though -- i'd use things a lot simpler than java for this purpose, but I digress...).
An outline of a solution would be:
call the process, having its input and output being handled as output/input streams from your caller java process.
read the output of your process until you are queried the password
write the password
carry on as needed.
If you need further clarification you may need to give more details about your scenario.
[1] http://docs.oracle.com/javase/7/docs/api/java/lang/ProcessBuilder.html
public class test {
public static void main(String[] args){
try {
System.out.println("");
String commands = "C:/swdtools/IBM/RAD8/scmtools/eclipse/scm.exe load -d C:/users/43793207/test -i test -r eric-repo";
// load -d C:/users/43793207/test -i test -r eric-repo
test test=new test();
test.execCommand(commands);
} catch (Exception e) {
e.printStackTrace();
}
}
public void execCommand(String commands){
//ProcessBuilder pb = new ProcessBuilder(Command);
//pb.start();
String line;
try {
//Process pp = Runtime.getRuntime().exec(commands);
System.out.println(commands);
Process process = new ProcessBuilder(commands).start();
InputStream is = process.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
while ((line = br.readLine()) != null) {
System.out.println(line);
}
} catch (IOException e) {
e.printStackTrace();
}
}
I was looking for a manner to execute several commans shell from java. I found this in stackoverflow but it helps only for executing one command shell per session :
try {
// Execute command
String command = "ls -la";
StringBuffer ret=new StringBuffer();
Process p = Runtime.getRuntime().exec(command);
// Get the input stream and read from it
InputStream in = child.getInputStream();
int c;
while ((c = in.read()) != -1) {
ret.append((char)c);
}
in.close();
System.out.println(ret.toString());
} catch (IOException e) {
e.printStackTrace();
}
is there anyway to execute many commands in the same session using code above ?
You can easily write this code inside a for-loop.
Perhaps you could group the commands in a shell script, and execute just that.
You can write an executable shell script or bat file with a bunch of commands and execute it as one command.
Firstly, that's not how you use Runtime.exec(): The first parameter is the executable, the others are the parameters to that executable.
Right now, your code is trying to execute a file called literally "ls -la", which of course doesn't exist.
Change your code to this:
String[] command = {"ls", "-la"}; // Use an array
Runtime.getRuntime().exec(command);
I want to run a shell script from a java program. This shell script invokes a system library which needs a big file as resource.
My java program calls this script for every word in a document. If I call this script again and again using Runtime.exec() the time taken is very high since the resource loading takes lot of time.
To overcome this I thought of writing the shell script as follows (to make it run continuously in background ):
count=0
while count -lt 10 ; do
read WORD
//execute command on this line
done
I need retrieve the output of the command in my java program and process it further.
How should I code the I/O operations for achieving this task?
I have tried writing words in to the process's output stream and reading back output from process's input stream. But this does not work and throws a broken pipe exception.
try {
parseResult = Runtime.getRuntime().exec(parseCommand);
parsingResultsReader = new BufferedReader(new InputStreamReader (parseResult.getInputStream()));
errorReader = new BufferedReader(new InputStreamReader (parseResult.getErrorStream()));
parseResultsWriter = new BufferedWriter(new OutputStreamWriter((parseResult.getOutputStream())));
} catch (IOException e) {
e.printStackTrace();
}
parseResultsWriter.write(word);
parseResultsWriter.flush();
while ((line = parsingResultsReader.readLine()) != null) {
// capture output in list here
}
Kindly help with this issue
//execute command on this line
Is this command a separate program? Then it will be launched for every word, so you'll get rid of only shell process which is lightweight anyway.
You have to learn how to run the heavyweight command for many words at once.
I am using libdmtx which comes with a command line utility which reads the image files for ECC200 Data Matrix barcodes, reads their contents, and writes the decoded messages to standard output. I have used command line utility in my java program on linux platform. I am using ubuntu linux. I have installed the libdmtx on my linux machine. and when I invoke the command
dmtxread -n /home/admin/ab.tif
on linux terminal it gives the decoded value of barcode in image immediately i.e within 15 seconds.
but when I am going to invoke this same command for same file using my java program the program takes huge time i.e average 16 minutes for the same command and same file above.
Following is my java code which invokes the above command
public class Test {
public static void main(final String[] args) throws IOException, InterruptedException {
//Build command
List<String> commands = new ArrayList<String>();
commands.add("dmtxread");
commands.add("-n");
commands.add("/home/admin/ab.tif");
System.out.println(commands);
//Run macro on target
ProcessBuilder pb = new ProcessBuilder(commands);
pb.redirectErrorStream(true);
Process process = pb.start();
//Read output
StringBuilder out = new StringBuilder();
BufferedReader br = new BufferedReader(new InputStreamReader(process.getInputStream()));
String line = null, previous = null;
while ((line = br.readLine()) != null){
System.out.println(line);
}
//Check result
if (process.waitFor() == 0)
System.out.println("Success!");
System.exit(0);
//Abnormal termination: Log command parameters and output and throw ExecutionException
System.err.println(commands);
System.err.println(out.toString());
System.exit(1);
}
}
I want to ask the experts that
Please can anyone explain me why java program takes such big time to invoke a simple command which will be get invoked withing 15 seconds if that command is directly run on command prompt.
Please can anyone tell me the solution to reduce this time.
I guess the program is taking this so much time because of JVMs internal thread which is invoking the process. Is my guess is right? If yes then how could I overcome to this problem.
Please guide me to solve this problem. Thanks You!