2011-03-09 7 views
10

tengo dicho código para leer un archivo de texto usando BufferedReader:¿El método BufferedReader.ready() asegura que el método readLine() no devuelve NULL?

BufferedReader reader=null; 
    try { 
     reader = new BufferedReader(new FileReader("file1.txt")); 

     while (reader.ready()) { 
      final String line = reader.readLine(); 
      System.out.println("<"+line+">"); 
     } catch (..) 
    { 
     ... 
    } 

funciona correctamente, pero Findbugs informes una advertencia:

NP_DEREFERENCE_OF_READLINE_VALUE: El resultado de invocar readLine() es dereferenced sin verificando si el resultado es nulo. Si no hay más líneas de texto para leer, readLine() devolverá nulo y desreferenciando que generará un puntero nulo excepción.

Cuando cambio FileReader-StringReader, es decir

BufferedReader reader=null; 
    try { 
     reader = new BufferedReader(new StringReader("ABCD")); 

     while (reader.ready()) { 
      final String line = reader.readLine(); 
      System.out.println("<"+line+">"); 
     } catch (..) 
    { 
     ... 
    } 

el método readLine devuelve null mientras que el método ready siempre devuelve true - de hecho este es un bucle infinito.

esto parece que el readLine puede volver null incluso si ready vuelve true. ¿Pero por qué el comportamiento difiere para diferentes Reader s?

ACTUALIZACIÓN:

conozco la forma normal para leer un archivo de texto (al igual que Pedro y Ali ilustrados). pero leí esa parte del código de mi colega y me di cuenta de que no conozco el método ready. Luego leo el JavaDoc, pero no entiendo block. Luego hice una prueba y publiqué esta pregunta. Entonces, la mejor manera de plantear esta pregunta podría ser:

¿Cuándo estará bloqueada la entrada? ¿Cómo usar el método ready (o por qué no usarlo)? ¿Por qué esos 2 Reader s (FileReader y StringReader) se comportan de manera diferente con respecto al método ready?

Respuesta

13

El método listos nos dice si la Corriente está listo para ser leído.

Imagine que su flujo de datos está leyendo desde un socket de red. En este caso, el flujo puede no haber finalizado, porque el socket no se ha cerrado, pero puede no estar listo para el siguiente fragmento de datos, porque el otro extremo del socket no ha enviado más datos.

En el escenario anterior, no podemos leer más datos hasta que el extremo remoto lo presione, por lo que debemos esperar a que los datos estén disponibles o que el socket se cierre. El método ready() nos dice cuando los datos están disponibles.

6

Esto es lo que los Javadocs tienen que decir:

indica si esta corriente está listo para ser leído. Una secuencia de caracteres almacenados en el búfer está lista si el búfer no está vacío o si la secuencia de caracteres subyacente está lista.

Así que un BufferedReader se considera listo simplemente si el secuencia subyacente también está listo. Como BufferedReader es un contenedor, este flujo subyacente podría ser cualquier implementación de Reader; por lo tanto, la semántica de ready() son los declarados en la interfaz:

devuelve verdadero si la siguiente lectura() se garantiza que no bloquear para la entrada, falso en caso contrario. Tenga en cuenta que devolver falso no garantiza que la siguiente lectura se bloquee.

Por lo que sólo consiguen realmente tiempo garantías, es decir que read() no bloqueará. El resultado de llamar al ready() no le dice absolutamente nada sobre el contenido que obtendrá de una llamada read(), por lo que no se puede utilizar para eludir una comprobación nula.

+6

Desafortunadamente para readLine(), ready() solo garantiza que un carácter esté disponible, es decir, read() no se bloqueará. readLine() bloqueará si hay datos pero no una línea completa. El código –

11

El Reader.ready() y InputStream.available() rara vez funcionan como te gustaría, y no sugiero que los uses. Para leer un archivo, debe usar

String line; 
while ((line = reader.readLine()) != null) 
    System.out.println("<"+line+">"); 
+3

se cuelga para siempre en esa línea reader.readline(). ¿Alguna sugerencia? – Paul

+1

Eso significa que el otro extremo no está enviando una nueva línea (posible otra cosa) –

+0

nah, eso no es todo; Lo hice en openssl en la línea de comandos muy bien – Paul

1

Mire the API for ready.

Lo que estás haciendo está mal. ready() solo le dice si la transmisión es legible y válida. Lea también el comentario en devolución en ese enlace.

Lo que se quiere hacer es:

String thisLine; 

//Loop across the arguments 
for (int i=0; i < args.length; i++) { 

    //Open the file for reading 
    try { 
    BufferedReader br = new BufferedReader(new FileReader(args[i])); 
    while ((thisLine = br.readLine()) != null) { // while loop begins here 
     System.out.println(thisLine); 
    } // end while 
    } // end try 
    catch (IOException e) { 
    System.err.println("Error: " + e); 
    } 
} // end for 
Cuestiones relacionadas