Search code examples
javastreamruntimeruntime.execprintstream

Printing Runtime exec() OutputStream to console


I am trying to get the OutputStream of the Process initiated by exec() to the console. How can this be done?

Here is some incomplete code:

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintStream;
import java.io.Reader;

public class RuntimeTests
{
    public static void main(String[] args)
    {
        File path = new File("C:\\Dir\\Dir2");
        String command = "cmd /c dir";
        Reader rdr = null;
        PrintStream prtStrm = System.out;
        try
        {
            Runtime terminal = Runtime.getRuntime();

            OutputStream rtm = terminal.exec(command, null, path).getOutputStream();
            prtStrm = new PrintStream(rtm);
            prtStrm.println();
        } 
        catch (IOException e)
        {
            e.printStackTrace();
        }
    }
}

Solution

  • See Benjamin Gruenbaum answer covering ProcessBuilder API available since Java 7.

    You need to start a new thread that would read process output happening after Process.waitFor(). Then process output can be copied the console from that thread.

    Process.getOutputStream() is actually the input, ie, stdin to the process. Process.getInputStream() and Process.getErrorStream() return InputStream objects which are the stdout and stderr of the process. The InputStreams and OutputStream are from the caller's perspective, which is the opposite of the process's perspective.

    The process's output, stdout, is input to the caller, therefore the caller gets a getInputStream() and reads the stdout from it:

    Process proc = Runtime.getRuntime().exec(cmdArr, env, cwdir);
    
    InputStreamReader isr = new InputStreamReader(proc.getInputStream());
    BufferedReader rdr = new BufferedReader(isr);
    while((line = rdr.readLine()) != null) { 
      System.out.println(line);
    } 
    
    isr = new InputStreamReader(proc.getErrorStream());
    rdr = new BufferedReader(isr);
    while((line = rdr.readLine()) != null) { 
      System.out.println(line);
    } 
    rc = proc.waitFor();  // Wait for the process to complete
    

    Process.getOutputStream() is used for the caller to 'output' data into the stdin of the process. This code could be added after 'proc' is created in the first line of the example above, to send data into stdin of the process:

    // Send data to stdin of the process (in development, needs input content)
    OutputStream os = proc.getOutputStream();
    Bytes content = new Bytes("Hello\nasdf\n adma");
    os.write(content.arr, content.off, content.length());
    os.close(); // should use try/finally or try/resource
    

    Do the above before reading the output. Remember to close the OutputStream os (either using try/resource or try/finally). So, the process knows that stdin is complete and it can finish processing the info.