Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

like image 834
Erik Avatar asked Aug 24 '10 07:08

Erik


4 Answers

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.

like image 163
Joachim Sauer Avatar answered Sep 25 '22 17:09

Joachim Sauer


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.

like image 36
Ashley Walton Avatar answered Sep 23 '22 17:09

Ashley Walton


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.
like image 34
joast Avatar answered Sep 24 '22 17:09

joast


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).

like image 26
extraneon Avatar answered Sep 21 '22 17:09

extraneon