views:

158

answers:

2

Can anyone give me an example of how to stream the output of an external program executed with DefaultExecutor? I'm not finding any documentation describing how to do this.

My external process will run for several hours, so just grabbing all output data isn't feasible; it must be streamed.

A: 

Note: this solution is synchronous, so it won't stream. You'll need to read is in a separate thread, or use the asynchronous version of the execute command.

private InputStream getStream() {

 String dataParsingCommand = "java";

PipedOutputStream output = new PipedOutputStream();
PumpStreamHandler psh = new PumpStreamHandler(output);

CommandLine cl = CommandLine.parse(command);
cl.addArgument("-jar");
cl.addArgument(dataParserPath);

DefaultExecutor exec = new DefaultExecutor();
DataInputStream is = null;
try {
    is = new DataInputStream(new PipedInputStream(output));
    exec.setStreamHandler(psh);
    exec.execute(dataParserCommandLine);
} catch (ExecuteException ex) {
} catch (IOException ex) {
}

return is;
}
Stefan Kendall
This probably won't work for the reason outlined in answers to your other question at http://stackoverflow.com/questions/2702834/commons-exec-hanging-when-i-call-executor-executecommandline
Christian Semrau
A: 

Below is some sample code for using Runtime.exec. it would be simple to adapt it to your use. From http://www.javaworld.com/javaworld/jw-12-2000/jw-1229-traps.html?page=4

import java.util.*;
import java.io.*;
class StreamGobbler extends Thread
{
    InputStream is;
    String type;

    StreamGobbler(InputStream is, String type)
    {
        this.is = is;
        this.type = type;
    }

    public void run()
    {
        try
        {
            InputStreamReader isr = new InputStreamReader(is);
            BufferedReader br = new BufferedReader(isr);
            String line=null;
            while ( (line = br.readLine()) != null)
                System.out.println(type + ">" + line);    
            } catch (IOException ioe)
              {
                ioe.printStackTrace();  
              }
    }
}

public class GoodWindowsExec { public static void main(String args[]) { if (args.length < 1) { System.out.println("USAGE: java GoodWindowsExec "); System.exit(1); }

    try
    {            
        String osName = System.getProperty("os.name" );
        String[] cmd = new String[3];
        if( osName.equals( "Windows NT" ) )
        {
            cmd[0] = "cmd.exe" ;
            cmd[1] = "/C" ;
            cmd[2] = args[0];
        }
        else if( osName.equals( "Windows 95" ) )
        {
            cmd[0] = "command.com" ;
            cmd[1] = "/C" ;
            cmd[2] = args[0];
        }

        Runtime rt = Runtime.getRuntime();
        System.out.println("Execing " + cmd[0] + " " + cmd[1] 
                           + " " + cmd[2]);
        Process proc = rt.exec(cmd);
        // any error message?
        StreamGobbler errorGobbler = new 
            StreamGobbler(proc.getErrorStream(), "ERROR");            

        // any output?
        StreamGobbler outputGobbler = new 
            StreamGobbler(proc.getInputStream(), "OUTPUT");

        // kick them off
        errorGobbler.start();
        outputGobbler.start();

        // any error???
        int exitVal = proc.waitFor();
        System.out.println("ExitValue: " + exitVal);        
    } catch (Throwable t)
      {
        t.printStackTrace();
      }
}

}

Romain Hippeau
The question was how to accomplish an process invocation using **commons-exec**, which wraps most of the stuff displayed in this answer.
Christian Semrau