views:

358

answers:

2

I am creating a GUI using Java. This GUI launches a program from the command line using the ProcessBuilder class.

A little information on the process being launched: from the command line, it creates another window and prints information to said window.

In my GUI window, I have a text area to where I would like to redirect said output. I originally intended to use a SwingWorker object to constantly check for more output and not hold up the GUI. To test and make sure I had the original syntax down (without even bringing the GUI into things) I thought I would print the output from the secondary process' window to System.out. However, something seems to be wrong as I can see the output in the secondary process' window, but not the terminal from which I am working.

Excerpt of code is as follows:

Process p = pb.start(); 
Scanner s = new Scanner(p.getInputStream());

SwingWorker pipe = new SwingWorker<String, Void> (){
    public String doInBackground(){
        while(run){
            if(s.hasNextLine()){
                System.out.println("S has next!");
                System.out.println(s.nextLine());
            }
        }
        return null;
    }
};
pipe.execute();

The boolean run is defined elsewhere in the program and is set to false when the process p exits or is force quit (additional question: is that a really bad idea? I feel like it might be...).

Does anyone have an idea as to why I am never getting any output when I see it being printed to the other window? Initially my reaction was to use p.getOutputStream() but Scanner does not take an outputStream as a paramter.

Thank you for your time.

+1  A: 

If the external process is writing its output to its own window, it is almost certain that the output is NOT being written to STDOUT, which is what you are reading with your code. If it did so, then the external program's output would be appearing both in its window and in the command line session from which it was launched (if one existed). Without access to the source of the external program it's unlikely you will be able to intercept its output unless the authors made provisions for that functionality (i.e. a command-line switch that redirects output to STDOUT instead of the window).

As to p.getOutputStream(), that returns a stream which is "output" from YOUR point of view -- i.e. you write to it to send data to the process' STDIN. Your use of p.getInputStream() would be correct for the case where the external program writes to its STDOUT.

Jim Garrison
Aha... so even if the window launched from the command line is another terminal window launched by this other process, it's output is not it's STDOUT? The process either prints information to an output file or it's window.
RCC
Most likely, yes. How do you control whether the process writes to a file or the secondary window? If this is Linux there's a chance it understands `-` as an output file meaning "write to STDOUT", in which case you could then use your code.
Jim Garrison
Unfortunately, it's Windows. The program itself takes arguments when it is invoked from the command line, with the name of the file to be written to after the keyword "output". If the program is supposed to write to the window the user just omits the output filename when calling the program.
RCC
Unless the programmer explicitly included a special keyword to cause output to STDOUT you're probably out of luck. There is another possibility but it's getting quite baroque -- write some code to emulate the Unix "tail" program to periodically poll the output file for more data. I'm not sure if this is possible from Java on Windows.
Jim Garrison
+1  A: 

You should also scan p.getErrorStream() - some programs write to STDERR which is indistinguishable from STDOUT when run from the command line. It is generally good practice to consume both streams, as if either one is not consumed it can cause the external process to hang.

Alex Vigdor
It in fact turns out that everything that the program was printing to the window was actually printing to STDERR. Interesting. Thanks!
RCC