Communicating with a command line tool in Java
I want to use a linux command line tool from my Java program. I start the program and get the output using the Process class (http://download.oracle.com/javase/6/docs/api/java/lang/Process.html):
/* @param args
* @throws IOException
*/
public static void main(String[] args) throws IOException {
Process proc = Runtime.getRuntime().exec("octave");
BufferedReader reader =
new BufferedReader(new InputStreamReader(proc.getInputStream()));
BufferedReader errorReader =
new BufferedReader(new InputStreamReader(proc.getInputStream()));
BufferedWriter writer =
new BufferedWriter(new OutputStreamWriter(proc.getOutputStream()));
int c;
while((c = proc.getInputStream().read()) != -1) {
System.out.print((char)c);
}
System.out.println("End");
}
I get the following output:
GNU Octave, version 3.0.5 Copyright (C) 2008 John W. Eaton and others. This is free software; see the source code for copying conditions. There is ABSOLUTELY NO WARRANTY; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For details, type `warranty'.
Octave was configured for "i486-pc-linux-gnu".
Additional information about Octave is available at http://www.octave.org.
Please contribute if you find this software useful. For more information, visit http://www.octave.org/help-wanted.html
Report bugs to (but first, please read http://www.octave.org/bugs.html to learn how to write a helpful report).
For information about changes from previous versions, type `news'.
The strange thing is the normal output if I run octave in the Terminal is the following:
:~/workspace/Console/src/c$ octave
GNU Octave, version 3.0.5 Copyright (C) 2008 John W. Eaton and others. This is free software; see the source code for copying conditions. There is ABSOLUTELY NO WARRANTY; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For details, type `warranty'. 开发者_开发问答Octave was configured for "i486-pc-linux-gnu".
Additional information about Octave is available at http://www.octave.org.
Please contribute if you find this software useful. For more information, visit http://www.octave.org/help-wanted.html
Report bugs to (but first, please read http://www.octave.org/bugs.html to learn how to write a helpful report).
For information about changes from previous versions, type `news'.
octave:1>
So the characters in the line where the input is requested are not sent in my input stream. Why? Isn't it possible to detect whether input is requested?
Thanks for your answers!
Heinrich
Programs on *nix can detect if they are talking to a terminal or another stream. And many interactive-shell-type programs react differently based on this (by setting different prompts, not reading some init files or even not starting at all).
You may be running into one of those situations.
Also, maybe using a Java API for octave may be the easier way: joPAS, for example.
Since your problem appears octave specific, I suggest using the --silent option for octave and passing all parameters on the command line in a single hit. This will work around the problems highlighted earlier about starting a terminal session.
You don't get the prompt, "octave:1> ", because octave's output is being buffered. Many programs that use stdio on Unix/Linux will do the same thing if the output is not to an interactive device. You won't receive the output until the buffer fills (automatically flushed) or the buffer is explicitly flushed by the program calling fflush(3).
If you really want to interact with a command line program, then you need to use a pty (something that I don't know is possible with java since I've never tried it).
Excerpt from "man stdio" that explains what is going on:
At program startup, three text streams are predefined and need not be opened explicitly -- standard input (for reading conventional input), standard output (for writing conventional input), and standard error (for writing diagnostic output). These streams are abbreviated stdin,stdout and stderr. When opened, the standard error stream is not fully buffered; the standard input and output streams are fully buffered if and only if the streams do not to refer to an interactive device. Output streams that refer to terminal devices are always line buffered by default; pending output to such streams is written automatically whenever an input stream that refers to a terminal device is read. In cases where a large amount of computation is done after printing part of a line on an output terminal, it is necessary to fflush(3) the stan- dard output before going off and computing so that the output will appear.
Could it be that it opens a new file descriptor for this prompt?
You might find that in the octave source code (or the readline source code if octave uses that).
I could finally solve the problem: Under Linux, use Octave with the --interactive and eventually the --no-line-editing optionand it worked :)
Heinrich
精彩评论