Search code examples
javabufferedreader

BufferedReader.readLine blocks my program but BufferedReader.read() reads properly


I have a snippet as follows:

Process proc = Runtime.getRuntime().exec(command);
BufferedReader br = new BufferedReader(new InputStreamReader(proc.getErrorStream()));
String line = br.readLine();

Now in the above code I am sure that process will always have on line input, so I did not use any kind of while loop or any null check. The problem is readLine blocks. The one reason I was aware of is, the stream having no data to read and hence readLine keeps waiting. To check this, I removed readLine and used read() function as follows:

Process proc = Runtime.getRuntime().exec( command );
BufferedReader br = new BufferedReader(new InputStreamReader(proc.getErrorStream()));
int a;
while((a=br.read())!=-1){
    char ch = (char) a;
    if(ch == '\n')
        System.out.print("New line "+ch);
    if(ch == '\r')
        System.out.print("Carriage return "+ch);
    System.out.print(ch);
}

To my surprise this code worked and printed the messags New line and Carriage return. Now I am wondering why did the readLine block? The data is available it is terminated by newline. What else could be the reason??

Note: The above worked once in a while! Maybe once out of 15times.
Note: I tried using ProcessBuilder too, but same behaviour.

UPDATE: So I switched to ProcessBuilder and then I redirected the errorStream and now I get both input stream and error stream at once when I do process.getInputStream and this works fine. Below is the snippet.

ProcessBuilder pb = new ProcessBuilder(command.split(" "));
pb..redirectErrorStream(true);
Process proc = pb.start();
BufferedReader br = new BufferedReader(new InputStreamReader(proc.getInputStream()));
String line = br.readLine();
//Now I get both input and error stream.

I would like to differentiate my error stream from input stream but with this method they are all jumbled up! Any ideas on this?


Solution

  • So to avoid getting the error stream and input stream merged just remove the line pb.redirectErrorStream(true);

    Because as said in the java doc :

    if this property is true, then any error output generated by subprocesses subsequently started by this object's start() method will be merged with the standard output, so that both can be read using the Process.getInputStream() method. This makes it easier to correlate error messages with the corresponding output. The initial value is false.

    By calling pb.redirectErrorStream(true); you are merging both output.