readline () devuelve nulo en Java

I'm trying to read the stdin in my Java program. I'm expecting a series of numbers followed by newlines, like:

6  
9  
1  

When providing the input through the eclipse built-in console, everything goes well. But when using the Windows command line, the program prints:

Received '6'.  
Received 'null'.  
Invalid input. Terminating. (This line is written by another function that does an Integer.parseint()).  

Mi codigo es:

static String readLineFromStdIn(){  
try{  
        java.io.BufferedReader stdin = new java.io.BufferedReader(new java.io.InputStreamReader(System.in));  
        String input = new String();  
        input = stdin.readLine();  
        System.out.println("Received '" + input + "'");  
        return(input);  
    }catch (java.io.IOException e) {  
        System.out.println(e);   
    }  
    return "This should not have happened";  
}  

¿Alguna pista?

preguntado el 09 de marzo de 12 a las 13:03

I enter the input in the Eclipse console, all numbers followed by enter. In windows I do "java -jar program.jar < input.txt". I have tried saving this 'input.txt' file both in UNIX and Windows coding. Didn't help. -

2 Respuestas

That you get a null indicates that the relevant Reader objects reached an EOF (end of file), or in other words that they can't get any more standard input. Now the obvious issues with your code are:

  1. Each method call to readLineFromStdIn() creará un Un nuevo BufferedReader.
  2. Cada uno de esos BufferedReader will be “competing” with each other for the same, shared input from System.in
  3. And none of these BufferedReader objects are ever properly closed, so your program leaks I/O resources with each call to readLineFromStdIn().

La solución es utilizar un soltero compartido BufferedReader object for each invocation of readLineFromStdIn().

respondido 09 mar '12, 13:03

Every time you open up a stdin , it technically means you're opening a file stream and you're never closing it which overshoots the possible number of open file connections that Java can hold. - kazekage gaara

@user268396 Note that if this BufferedReader were closed it would also close System.in which may not be desirable. This could be a rare case where you just want the decorator streams to be GC'd without being closed. - Dev

Agreed you don't want to cause System.in to be closed explicitly. However it be closed anyway when the BufferedReader is GC'ed. There are finalizers to that extent, IIRC. I guess what happened before the fix was that on the Windows VM the temporary BufferedReader objects were GC'ed very agressively and hence caused STDIN to be closed before the second readLineFromStdIn call (hence the null, trying to read from a closed System.in). - user268396

Not really a new answer to this question, but I wanted to clear up confusion in the comments about why the original code behaved as it did (I can't comment because I'm new to ST and haven't garnered reputation points).

The null result has nothing to do with garbage collection. The following program suffers exactly the same fate even though both readers still live, accessible objects:

BufferedReader r1 = new BufferedReader(new InputStreamReader(System.in));
System.out.println(r1.readLine());
BufferedReader r2 = new BufferedReader(new InputStreamReader(System.in));
System.out.println(r2.readLine());

It all comes down to what "Buffered" means in BufferedReader. Es un Reader that includes internal buffering. The internal buffering usually significantly improves the efficiency of operations on the underlying stream, e.g. by attempting to read a full buffer's worth each time, rather than nickle-and-diming the stream to death getting a few bytes here and a few there.

So what happens when you create the first BufferedReader on stdin and read a line from it? That BufferedReader reads a buffer-full from the stream, detects the end of line, returns the first line, and hangs on to the rest of the buffer to fill its next request. That leaves the underlying stream positioned beyond the end of that first line. And if your input is small, it could easily be positioned at EOF.

So now you come along and create a second BufferedReader atop the same stream - which is at EOF - and attempt to get a line. The second BufferedReader attempts to read from the underlying stream and detects EOF, so readLine devoluciones null.

Respondido 11 Feb 14, 21:02

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.