CodeGym /Blog Java /Random-ES /Lectura desde el teclado: "lectores"
Autor
Aditi Nawghare
Software Engineer at Siemens

Lectura desde el teclado: "lectores"

Publicado en el grupo Random-ES
¡Hola! Las lecciones y tareas en el Nivel 3 le enseñaron cómo mostrar cosas en la consola y, moviéndose en la otra dirección, cómo leer datos desde el teclado.
Lectura desde el teclado: "lectores" - 1
Incluso aprendiste a usar la siguiente construcción compleja para lograr esto:

BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
Pero hay una pregunta que aún no hemos respondido.

¿Cómo en el mundo funciona esto?

En realidad, los programas rara vez son completamente independientes. Se comunican con otros programas, sistemas, Internet, etc. Por "comunicar", nos referimos principalmente a "intercambiar datos". Es decir, reciben algunos datos externos y también envían datos del programa interno a alguna parte. Los ejemplos de programas que intercambian datos abundan en la vida cotidiana. Por ejemplo, muchos sitios web le permiten iniciar sesión con su cuenta de Facebook o Twitter en lugar de registrarse. En esta situación, dos programas (p. ej., Twitter y el sitio web en el que se está registrando) intercambian los datos necesarios. El resultado final es que ha iniciado sesión correctamente. La palabra "transmisión"se utiliza para describir el proceso de intercambio de datos. ¿De dónde viene este nombre? En su experiencia, un "arroyo" puede estar más asociado con los ríos y que con la programación. Eso no es un accidente :) Una transmisión es, en esencia, una pieza de datos en movimiento. En otras palabras, en la programación, no es agua lo que fluye, sino datos en forma de bytes y caracteres. Podemos recibir bits de datos de un flujo de datos y luego usarlos. Nuevamente, usaremos la analogía agua/flujo: puedes sacar agua de un río para hacer sopa, apagar un fuego o regar tus flores. Los flujos le permiten trabajar con cualquier fuente de datos: ya sea Internet, el sistema de archivos de su computadora u otra cosa, no hay diferencia. Los streams son una herramienta universal. Permiten que un programa reciba datos desde cualquier lugar (flujos de entrada) y los envíe a cualquier lugar (flujos de salida). Su tarea es la misma: tomar datos de un lugar y enviarlos a otro. Hay dos tipos de flujos:
  1. Los flujos de entrada se utilizan para recibir datos.
  2. Los flujos de salida son para enviar datos.
En Java, estos flujos son implementados por las clases InputStreamy OutputStream. Pero las corrientes se pueden categorizar de otra manera. Además de flujos de entrada y salida, también hablamos de flujos de bytes y flujos de caracteres . El significado aquí debería ser lo suficientemente claro: el flujo de bytes envía información como un conjunto de bytes, mientras que un flujo de caracteres la envía como un conjunto de caracteres. En esta lección, nos detendremos en los flujos de entrada. Pondré un enlace con información sobre flujos de salida al final de la lección. Puedes leerlo por tu cuenta :) Ahora echa un vistazo a este código:

BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
Al pasar por las lecciones, ¿no pensó que esta línea era bastante intimidante? :) Ese no será el caso una vez que hayamos explorado cómo funciona. Arreglemos las cosas. Empezaremos por el final. System.ines un InputStreamobjeto, una instancia de la clase de la que hablamos antes. Es un flujo de entrada vinculado a un dispositivo de entrada del sistema (el teclado). Por cierto, estás indirectamente familiarizado con esta transmisión. Después de todo, con frecuencia usa su "compañero de trabajo" — System.out! System.outes el flujo de salida del sistema . Se usa para enviar datos a la consola a través de su método favorito System.out.println(), que usa constantemente :) System.outes un flujo para enviar datos a la consola, mientras queSystem.ines para obtener datos del teclado. Todo es simple :) Además, podemos leer datos desde el teclado sin esta enorme construcción. Simplemente podemos escribir: System.in.read();

public class Main {

   public static void main(String[] args) throws IOException {

       while (true) {
           int x = System.in.read();
           System.out.println(x);
       }
   }
}
La InputStreamclase (recuerde, System.ines un InputStreamobjeto) tiene un read()método que le permite leer datos. Hay un problema: lee bytes , no caracteres . Es aburrido usar solo letras en inglés, así que intentemos leer el carácter chino "魚" desde el teclado (simplemente copie esta letra desde aquí y péguela en la consola usando ctrl + v en PC o Comando + v en Mac). Este carácter significa 'un pez' por cierto. Salida de consola: 233 173 154 10 Este símbolo y muchos otros chinos ocupan 3 bytes en la memoria de la computadora (a diferencia de las letras latinas, que ocupan solo 1 byte). En este caso, se leen 4 bytes del flujo: los primeros tres representan el carácter "魚", y el otro byte representa una nueva línea (Enter). En consecuencia, System.inen su forma sin adornos no es una opción para nosotros. Los humanos (¡con raras excepciones!) no saben leer bytes. ¡ Pero la InputStreamReaderclase viene al rescate! Veamos qué tipo de animal es este.

BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
Pasamos System.inal objeto InputStreamReader . ¡El nombre de la clase lo dice! Creamos un InputStreamReaderobjeto y le pasamos un flujo de entrada del que leerá los datos. En este caso...

new InputStreamReader(System.in)
...le decimos, "leerás datos del flujo de entrada del sistema (desde el teclado)". ¡Pero esta no es su única función! El InputStreamReaderno solo recibe datos de la transmisión. También convierte secuencias de bytes en secuencias de caracteres . En otras palabras, ya no necesita convertir los datos de "unos y ceros" a un "lenguaje legible por humanos". InputStreamreaderhace todo por ti. Por supuesto, InputStreamReaderno se limita a leer datos de la consola. También puede leer datos de otros lugares. Por ejemplo, de un archivo:

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;

public class Main {

   public static void main(String[] args) throws IOException {
       InputStreamReader inputStreamReader = new InputStreamReader(new FileInputStream("C:\\Users\\username\\Desktop\\testFile.txt"));
   }
}
Aquí creamos un FileInputStream(un tipo de InputStream), pasamos la ruta del archivo y pasamos la transmisión en sí al InputStreamReader. Ahora podrá leer datos del archivo (si existe un archivo en la ruta, por supuesto). También usamos el método InputStreamReaderde la clase read()para leer datos (la fuente de los datos no importa: la consola, un archivo o algún otro lugar). ¿Cuál es la diferencia entre System.in.read()y InputStreamReader.read()?\ Intentemos nuevamente leer el carácter "魚" con un InputStreamReader. Les recuerdo lo que realmente leyó System.in.read(): 233 173 154 10 ¿Y cómo funciona InputStreamReaderel mismo?

public class Main {

   public static void main(String[] args) throws IOException {

       InputStreamReader reader = new InputStreamReader(System.in);
       while (true) {
           int x = reader.read();
           System.out.println(x);
       }
   }
}
Salida de la consola: 39770 10 La diferencia es evidente de inmediato. El último byte (que representa la nueva línea) permanece sin cambios (el número 10), pero el carácter "魚" se convirtió en un solo código "39770". ¡Esto es lo que significa leer caracteres! Si no crees que 39770 representa la letra "魚", es fácil convencerte :)
import java.io.IOException;

public class Main {

   public static void main(String[] args) throws IOException {

       char x = 39770;
       System.out.println(x);
   }
}
Salida de la consola: Pero si InputStreamReaderes tan bueno, ¿por qué también lo necesitamos BufferedReader? InputStreamReadersabe cómo leer datos y convertir bytes en caracteres. ¿Qué más podemos pedir? ¿Por qué otro lector? :/ La respuesta es muy sencilla: para un mayor rendimiento y comodidad . Comencemos con el rendimiento. Cuando BufferedReaderlee datos, utiliza un área especial llamada búfer, donde "almacena" los caracteres que lee. En última instancia, cuando se necesiten estos caracteres en el programa, se tomarán del búfer, no directamente de la fuente de datos (teclado, archivo, etc.). Esto ahorra muchos recursos. Para entender cómo funciona esto, imagina un mensajero en una gran empresa. El mensajero se sienta en una oficina, esperando que alguien traiga paquetes para entregar. Cada vez que recibe un paquete nuevo, puede ponerse en marcha inmediatamente. Pero podría haber muchos paquetes durante el día. Tendría que hacer muchos viajes entre la oficina y las direcciones de entrega. En cambio, el mensajero pone una caja en su oficina. Todos ponen sus paquetes en la caja. Ahora el mensajero puede tomar la caja con calma y moverse de una dirección a otra. Esto ahorra mucho tiempo, porque no tiene que volver a la oficina cada vez. En este ejemplo, la caja es solo un búfer y la oficina es una fuente de datos. Es mucho más fácil para el mensajero tomar paquetes de una sola caja al hacer las entregas que volver a la oficina cada vez. También ahorrará gasolina. De manera similar, en un programa es mucho menos intensivo en recursos tomar datos de un búfer que hacer referencia a la fuente de datos cada vez. Como resultado,BufferedReader+ InputStreamReaderes más rápido que InputStreamReadersolo . Hemos considerado el rendimiento. ¿Qué pasa con la conveniencia? La principal ventaja es que Bufferedreaderpuede leer datos no solo de un carácter a la vez (aunque puede hacerlo con su read()método), ¡sino también líneas completas a la vez! Esto se hace usando el readLine()método;

public class Main {

   public static void main(String[] args) throws IOException {

       BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
       String s = reader.readLine();
       System.out.println("We read this line from the keyboard:");
       System.out.println(s);
   }
}
Salida de la consola: ¡CodeGym es el mejor sitio web para aprender Java! Leemos esta línea del teclado: ¡CodeGym es el mejor sitio web para aprender Java! Esto es especialmente útil cuando se leen grandes cantidades de datos. Todavía es factible leer una o dos líneas de texto carácter por carácter. Pero leer en "Guerra y paz" una letra a la vez sería algo problemático :)
Comentarios
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION