BufferedReader input attempt from System.in throwing exceptions

John Tate picture John Tate · Jun 18, 2013 · Viewed 16.6k times · Source

I am trying to read a from the input using BufferedReader. It works the first time but the second time it is ran I get an exception.

john@fekete:~/devel/java/pricecalc$ java frontend.CUI 
> gsdfgd
Invalid command!
> I/O Error getting string:  java.io.IOException: Stream closed
I/O Error: java.io.IOException: java.io.IOException: Stream closed
> I/O Error getting string:  java.io.IOException: Stream closed
I/O Error: java.io.IOException: java.io.IOException: Stream closed
> I/O Error getting string:  java.io.IOException: Stream closed

It just keeps running with that in a loop. I must have missed something.

public static void main(String args[]) {
            if (args.length == 0) {
                    while (!exit) {
                            try {
                                    exit = processLine(commandLine());
                            } catch (IOException e) {
                                    System.out.println("I/O Error: " + e);
                            }
                    }
                    System.out.println("Bye!");
            } else if (args.length == 1) {
                    String line = new String(args[0]);
                    processLine(line);
            } else {
                    String line = new String(args[0]);
                    for (String np : args) {
                            line = new String(line + " " + np); 
                    }
                    processLine(line);
            }
    }

    static private String commandLine() throws IOException {
            String str = new String();
            try (BufferedReader br = new BufferedReader(new InputStreamReader(System.in))) {
                    System.out.print("> ");
                    str = new String(br.readLine());
                    str = str.trim();
            } catch (IOException e) {
                    System.out.println("I/O Error getting string: "+ str + " " + e);
                    throw new IOException(e);
            }

            return str;
    }

It really all seems to be about commandLine() not working so I've just included that and main.

Answer

Jon Skeet picture Jon Skeet · Jun 18, 2013

Yes, you're closing the stream here:

try (BufferedReader br = new BufferedReader(new InputStreamReader(System.in)))

That try-with-resources statement will close the BufferedReader at the end of the block, which will close the InputStreamReader, which will close System.in.

You don't want to do that in this case, so just use:

// Deliberately not closing System.in!
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));   
try {
    ...
}

It's still possible that this won't quite behave as you want though, as the BufferedReader could potentially consume (and buffer) more data. You'd be better off creating the BufferedReader once (in the calling code) and passing it to the method.

Oh, and I suggest you get rid of this:

String str = new String();

There's no need for it at all. This would be better:

String str = "";

But even then, it's a pointless assignment. Likewise you don't need to create a new String from the one returned by readLine(). Just use:

return br.readLine().trim();

... within the try block. Also, there's no point in logging str within the catch block, as it's going to be empty - the IOException will only be thrown when reading the line...