2

Este es el código pero no sale del programa, por lo que veo es que no me evalúa la variable como null:

import java.io.*;

class Fichero3 {

 public static void main(String[] args) {
   BufferedReader teclado; 
   String x;
   InputStreamReader inStream;
   inStream=new InputStreamReader(System.in); 
   teclado = new BufferedReader(inStream); 

   File fSalida = new File("prueba.salida"); 
   try {
      String s;
      FileWriter fwSalida = new FileWriter(fSalida); 
      PrintWriter w = new PrintWriter(fwSalida); 

      while ((s = teclado.readLine())!=null ) {
        w.println(s);
        System.out.println(s);

        if (s == "final"){
          s = null;
          System.out.println(s);
        }

       System.out.println(s.getClass());
    }

    fwSalida.close(); 
    inStream.close();

  } catch (FileNotFoundException e) {
    System.err.println("Fichero. no encontrado");

  }  catch (IOException e) { 
    System.err.println("Error de E/S");
  }
} 
Jorgesys
  • 103,630
  • 13
  • 52
  • 124
bruno celaya
  • 109
  • 1
  • 1
  • 5
  • Tienes `2String` en ves de `String` – cignius Feb 27 '17 at 18:41
  • 1
    @Cig: Fue un error en una de las ediciones, no error de OP. Lo acaba de corregir. – sstan Feb 27 '17 at 18:41
  • 1
    Posible duplicado de [¿Cómo comparar correctamente Strings en Java?](http://es.stackoverflow.com/questions/225/c%c3%b3mo-comparar-correctamente-strings-en-java). Al menos, es una parte de la respuesta a tu problema. – sstan Feb 27 '17 at 18:43
  • Gracias por esta pregunta tan interesante bruno. Espero que podamos verte más por aquí. +1 – Anonymous Coward Feb 27 '17 at 23:12

3 Answers3

3

La comparación con null funciona bien. Y tu código al comparar con null es correcto.

Como indica la documentación de java sobre readLine este método devuelve null cuando se llega al final del stream.
Es posible que esto no lo hayas observado porque al usar la entrada estandar nunca hayas llegado al final del stream. Pero se puede producir. Obsérva por ejemplo tu programa (solo le he quitado la escritura en fichero y añadido unos println para que se vea lo que hace) en ideone.

Ponle como entrada (en input) :

matarife
Linurillo

Y tenemos como salida :

matarife
class java.lang.String
Linurillo
class java.lang.String
He terminado

Como puedes ver tu programa termina. La comparación con null funciona correctamente. Se ha detectado bien el fin del stream.

No cambies esta línea correcta de tu programa:

  while ((s = teclado.readLine())!=null ) {

Por esta línea incorrecta:

 while (!(s = teclado.readLine()).equals("final")) {

Puesto que si lo hicieses estarías empeorando tu programa. Estarías introduciendo la posibilidad de exepciones NullPointerException. Como puedes ver aqui.

¿Que está mal entonces?
El error lo podemos observar cambiando la entrada del programa anterior por :

matarife
final
Linurillo

Y la salida es:

matarife
class java.lang.String
final
class java.lang.String
Linurillo
class java.lang.String
He terminado

El programa sigue terminando, sale del bucle. Pero no se para en final como quieres sino que sigue leyendo hasta agotar todo el stream.

Por una parte la comparación de la cadena que debiera ser con equals y no con ==, es decir, has de usar :

if (s.equals("final")){

Mas detalles sobre la comparación de cadenas en la pregunta que enlaza sstan: ¿Cómo comparar correctamente Strings en Java?

Y en segundo lugar la salida del bucle. Con asignar null a s no sirve. Porque luego ese valor va a ser sobreescrito por (s = teclado.readLine()) antes de que se compare con null. Sencillamente haz un break;

    if (s.equals("final")){
      System.out.println(s);
      break;
    }

Tal como lo he puesto esto provocará una pequeña alteración en el funcionamiento de tu programa. No se imprime el último System.out.println(s.getClass()); del bucle. Pero seguro que esto lo puedes solucionar tu mismo.

Anonymous Coward
  • 6,185
  • 4
  • 31
  • 58
  • 1
    Quieres que el usuario mismo se da cuenta donde "más correcta" no es? :) Ahora ambos tenemos "code smell", solamente distinto. Buena respuesta aun, menos el uso de la palabra "correcta/incorrecta". ;) – Stefan Nolde Mar 01 '17 at 12:57
  • 1
    Me gustaría debatirlo en [el chat](http://chat.stackexchange.com/rooms/53063/npe-o-resultado-vacio) en algun momento. – Stefan Nolde Mar 01 '17 at 13:03
2

Tu nunca sales del while porque siempre vuelves a tratar de nuevo de leer de stdin.

Cambia:

 while ((s = teclado.readLine())!=null ) {
    w.println(s);
    System.out.println(s);

    if (s == "final"){
      s = null;
      System.out.println(s);
    }

   System.out.println(s.getClass());
} 

a

while (!(s = teclado.readLine()).equals("final") ) {
    w.println(s);
    System.out.println(s);

   System.out.println(s.getClass());
}

Aquí empieza la parte que es parcialmente basado en opiniónes

Esta respuesta no considera producir código de producción, Jose Dura Antonio Olmos te daba una respuesta "más canónica", aun no completa todavía.

En el caso particular no te tienes que proteger necesariamente de una NPE en el while, porque una NPE en el InputStream del sistema es suficientemente fuera de lo normal de rectificar la terminación de tu programa por ella, y los recursos se liberan cuando la VM termina. La NPE en este caso esta causado por remplazar el InputStream de la consola por otro.

Si apuntas a producir código solido para un sistema de producción, tienes que considerar con más importancia lo que pasa en el caso de una excepción en el close() de la salida, porque eso saltaría el close()de la entrada y podría significar que el recurso no se libera.

Si hablamos de "correcto" se debería colocar los close en un finally:

try{
    ...
} catch (Exception e) {
    ...
} finally {
    try { fwSalida.close(); } catch (Exception e) {};
    try { inStream.close(); } catch (Exception e) {};
}

Siempre se puede un poco más "correcto". ;)

Stefan Nolde
  • 6,648
  • 1
  • 24
  • 44
1

No es que no detecte null, lo que sucede es la comparación que realizas, es incorrecta, la comparación de Strings se realiza mediante equals(), por esta razón tu programa no funcionaría correctamente, usa equals(), ejemplo:

//  if (s == "final"){
  if (s.equals("final")){
      s = null;
      System.out.println(s);
    }

Este sería código en el loop while para corregir el detalle, incluso la comparación dentro del while no es necesaria:

 while (!(s = teclado.readLine()).equals("final")) {
        w.println(s);
        System.out.println(s);

        /*if (s.equals("final")){
          s = null;
          System.out.println(s);
        }*/

       System.out.println(s.getClass());
    }

Te recomiendo revisar esta pregunta:

¿Cómo comparar correctamente Strings en Java?

Jorgesys
  • 103,630
  • 13
  • 52
  • 124
  • hola @sstan pense como tu definirla como duplicado, pero el usuario busca "Programa no me detecta Null", creo que es parte del problema por eso pongo la referencia. Que opinas? – Jorgesys Feb 27 '17 at 19:18
  • jeje, lo dejo a tu criterio. Lo que sí diré es que cada respuesta/post parece tener una parte del rompe cabeza. Por ejemplo, tanto tu como yo nos centramos en la forma de comparar los Strings. Pero aun la solución que propones (y la que yo tenía pensada inicialmente) no solucionan el problema enteramente debido a que el `while` vuelve a asignar un nuevo valor a `s`. Por eso, en este caso, la respuesta de Stefan es la mas correcta. – sstan Feb 27 '17 at 19:24
  • yap! while (!(s = teclado.readLine()).equals("final")) { dentro de asigna el valor null y en el while se valida el string :P – Jorgesys Feb 27 '17 at 19:27
  • Ohoh, Me estoy arriesgando a parecerme a otro usuario que tanto quieres :) Pero si aplicas esa corrección al `while`, entonces concordarás que el `if` dentro del bucle no sirve de nada. Pero si lo quitas, entonces tu respuesta viene siendo la misma que la de Stefan :) – sstan Feb 27 '17 at 19:32
  • @sstan no!, al contrario, agradezco las observaciones, de hecho no había visto esto que comentas, y la asignación de null a la variable s!, de hecho estoy "algo" ocupad@, pero te puedo decir que la asignación de s = null; sirve, pero de adorno haha! agradezco la ayuda! ᕦ ´• ᴥ •` ᕥ – Jorgesys Feb 27 '17 at 19:44