Search code examples
javaprocessprocessbuilder

What is the difference between different ProcessBuilder.redirectInput()?


I went through the documentation of ProcessBuilder but I am having trouble understanding the difference between

  1. processBuiler.inheritIO()
  2. processBuilder.redirectInput(ProcessBuilder.Redirect.PIPE)
  3. processBuilder.redirectInput(ProcessBuilder.Redirect.INHERIT)

FROM DOC: ProcessBuilder.Redirect PIPE: Indicates that subprocess I/O will be connected to the current Java process over a pipe. This is the default handling of subprocess standard I/O.

  1. what is a pipe here?

  2. when and where would you use each one of them?

  3. based on the docs what is the diff between 1 and 3 then?

If this question is not fit for stackoverflow, please point me in the right direction as to where to ask this.


Solution

  • PIPE means that the I/O streams of the process will be obtainable via Process#getInputStream, Process#getErrorStream and Process#getOutputStream. This is different from INHERIT, which merges a stream with the stream of the current Java process, that is, System.out, System.in, or System.err.

    When you call ProcessBuilder#inheritIO, you are redirecting all I/O streams to the System.

    When you call redirectInput(ProcessBuilder.Redirect.PIPE), you are redirecting only the input to the PIPE.

    When you call redirectInput(ProcessBuilder.Redirect.INHERIT), you are redirecting only the input to the System.

    So, the difference between 1st and 3d is that 3d call redirects only the input of the process, while the 1st one redirects all I/O streams.

    You should use INHERIT when you want to use a stream of the Process via the stream of the System.

    And you should use PIPE when you want to handle a stream of the Process separately. Consider following example:

    public class ProcessTest {
        @Test
        public void testProcess() throws IOException {
    
            //all streams go to System streams
            new ProcessBuilder("java","--version").inheritIO().start();
    
            //all streams are kept separate, and are obtained via .get...Stream() calls 
            Process process2=new ProcessBuilder("java","--version").start();
            BufferedReader bufferedReader=new BufferedReader(new InputStreamReader(process2.getInputStream()));
            String s;
            while ((s=bufferedReader.readLine())!=null)
            {
                System.out.println(s);
            }
            bufferedReader.close();
    
            //only the output of the Process is going to the System.out
            new ProcessBuilder("java","--version").redirectOutput(ProcessBuilder.Redirect.INHERIT).start();
    
        }
    }