¡Hola! En conferencias y tareas, aprendimos cómo enviar datos a la consola y viceversa: leer datos desde el teclado. Incluso aprendiste a utilizar una construcción compleja para esto:
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
Pero todavía no hemos respondido una pregunta.
¿Cómo funciona esto?
De hecho, la mayoría de las veces ningún programa existe por sí solo. Puede comunicarse con otros programas, sistemas, Internet, etc. Con la palabra "comunicar" nos referimos en primer lugar a "intercambiar datos". Es decir, recibir algunos datos del exterior y, por el contrario, enviar tus propios datos a alguna parte. Hay muchos ejemplos de intercambio de datos entre programas, incluso en la vida cotidiana. Entonces, en muchos sitios, en lugar de registrarse, puede iniciar sesión usando su cuenta de Facebook o Twitter. En esta situación, dos programas, digamos Twitter y el sitio donde está intentando registrarse, intercambian los datos necesarios entre sí, después de lo cual se ve el resultado final: una autorización exitosa. El término " flujo " se utiliza a menudo para describir el proceso de intercambio de datos en programación . ¿De dónde viene este nombre? El “flujo” está más asociado con un río o arroyo que con la programación. De hecho, esto no es sin razón :) Una secuencia es, en esencia, un dato en movimiento. Es decir, en programación no es agua lo que “fluye” a lo largo del arroyo, sino datos en forma de bytes y caracteres. A partir de un flujo de datos, podemos recibir datos en partes y hacer algo con ellos. Nuevamente, usemos la analogía del “agua que fluye”: puedes sacar agua de un río para cocinar sopa, apagar un fuego o regar flores. Con las transmisiones, puede trabajar con cualquier fuente de datos: Internet, el sistema de archivos de su computadora o cualquier otra cosa, no importa. Las transmisiones son una herramienta universal. Permiten que el programa reciba datos desde cualquier lugar (flujos entrantes) y los envíe a cualquier lugar (flujos salientes). Su tarea es una: tomar datos en un lugar y enviarlos a otro. Las corrientes se dividen en dos tipos:- Flujo entrante ( entrada ): se utiliza para recibir datos
- Flujo saliente ( Salida ): para enviar datos.
InputStream
y el flujo de datos salientes en la clase OutputStream
. Pero hay otra forma de dividir los hilos. Se dividen no solo en entrantes y salientes, sino también en bytes y caracteres . Aquí el significado es claro sin explicación: un flujo de bytes transmite información en forma de un conjunto de bytes y un flujo de caracteres transmite información en forma de un conjunto de caracteres. En esta conferencia entraremos en detalles sobre las transmisiones entrantes. Y adjuntaré información sobre los enlaces salientes al final, y puedes leerlo tú mismo :) Entonces, nuestro código:
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
¿Probablemente pensaste mientras leías las conferencias que parecían bastante aterradoras? :) Pero esto es sólo hasta que descubramos cómo funciona esto. ¡Arreglemoslo ahora! Empecemos por el final. System.in
es un objeto de la clase InputStream
de la que hablamos al principio. Esta es una transmisión entrante y está vinculada al dispositivo de entrada del sistema: el teclado. Por cierto, estás indirectamente familiarizado con él. Después de todo, a menudo utilizas a su "colega" en tu trabajo System.out
. System.out
- este es un flujo de salida de datos del sistema , se usa para enviar a la consola en el mismo método System.out.println()
que usa constantemente :) System.out
- un flujo para enviar datos a la consola y System.in
- para recibir datos desde el teclado. Es simple :) Además: para leer datos desde el teclado, podemos prescindir de esta gran construcción y simplemente 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);
}
}
}
En la clase InputStream
(y System.in
, déjame recordarte, es un objeto de la clase InputStream
) hay un método read()
que te permite leer datos. Un problema: lee bytes , no caracteres . Intentemos leer la letra rusa "Ya" desde el teclado. Salida de consola:
Я
208
175
10
Las letras rusas ocupan 2 bytes en la memoria de la computadora (a diferencia de las letras inglesas, que ocupan solo 1). En este caso, se leyeron 3 bytes del flujo: los dos primeros representan nuestra letra “I”, y el otro es el salto de línea (Enter). Por tanto, la opción de utilizar “desnudo” System.in
no nos conviene. Los humanos (¡con raras excepciones!) no pueden leer bytes. ¡Aquí es donde la próxima clase viene en nuestra ayuda InputStreamReader
! Averigüemos qué tipo de animal es este.
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
Pasamos el arroyo System.in
al InputStreamReader
. En general, si traduces su nombre al ruso, todo parece obvio: "lector de transmisiones entrantes". En realidad, ¡para eso es exactamente! Creamos un objeto de clase InputStreamReader
y le pasamos una secuencia entrante de la cual debería leer datos. En este caso...
new InputStreamReader(System.in)
...le decimos: "leerás datos del flujo de entrada del sistema (teclado)". ¡Pero ésta no es su única función! InputStreamReader
no solo recibe datos de la transmisión. También convierte flujos de bytes en flujos de caracteres . En otras palabras, ya no tendrá que preocuparse por traducir los datos leídos del lenguaje "computador" al lenguaje "humano": InputStreamReader
él hará todo por usted. InputStreamReader
Por supuesto, puede leer datos no solo de la consola, sino también de otros lugares. Por ejemplo, del 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 flujo de datos entrante FileInputStream
(esta es una de las variedades InputStream
), le pasamos la ruta al archivo y le pasamos el flujo en sí InputStreamReader
. Ahora podrá leer datos de este archivo, si el archivo en esta ruta existe, por supuesto. Para leer datos (sin importar desde dónde, desde la consola, un archivo o cualquier otro lugar), la clase InputStreamReader
también usa el archivo read()
. ¿ Cuál es la diferencia entre System.in.read()
y InputStreamReader.read()
? Intentemos contar la misma letra “I” usando InputStreamReader
. Déjame recordarte que esto es lo que pensé System.in.read()
:
Я
208
175
10
¿Cómo puede hacer el mismo trabajo InputStreamReader
?
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 consola:
Я
1071
10
La diferencia es inmediatamente visible. El último byte, para los saltos de línea, permaneció sin cambios (el número 10), pero la letra leída "I" se convirtió en un código único "1071". ¡Esto es lectura por símbolos! Si de repente no crees que el código 1071 significa la letra “I”, es fácil verificarlo :)
import java.io.IOException;
public class Main {
public static void main(String[] args) throws IOException {
char x = 1071;
System.out.println(x);
}
}
Salida de consola:
Я
Pero si InputStreamReader
es tan bueno, ¿por qué necesitas más BufferedReader
? InputStreamReader
Podemos leer datos y convertir bytes en caracteres. ¿Qué más necesitamos? ¿Por qué otro lector? :/ La respuesta es muy simple: para mayor productividad y mayor comodidad . Empecemos por el rendimiento. Al leer datos, BufferedReader utiliza un área especial, un búfer, donde "agrega" los caracteres leídos. Como resultado, cuando necesitemos estos caracteres en el programa, se tomarán del búfer y no directamente de la fuente de datos (teclado, archivo, etc.), y esto ahorra muchos recursos. Para entender cómo funciona esto, imaginemos, por ejemplo, el trabajo de un mensajero en una gran empresa. El mensajero se sienta en la oficina y espera que le traigan los paquetes para su entrega. Cada vez que recibe un nuevo paquete, puede salir a la carretera inmediatamente. Pero puede haber muchos paquetes durante el día y tendrá que viajar entre la oficina y las direcciones cada vez. En cambio, el mensajero colocó una caja en la oficina donde todos podían poner sus paquetes. Ahora el mensajero puede tomar tranquilamente la caja e ir a las direcciones; ahorrará mucho tiempo porque no tendrá que regresar a la oficina cada vez. El cuadro de este ejemplo es precisamente el búfer y la oficina es la fuente de datos. Es mucho más fácil para un mensajero sacar una carta de un buzón común al entregarla que ir a la oficina cada vez. También ahorrará gasolina. Lo mismo ocurre en un programa: requiere muchos menos recursos tomar datos del búfer, en lugar de acceder a la fuente de datos cada vez. Por eso BufferedReader
+ InputStreamReader
funciona más rápido que solo InputStreamReader
. Hemos solucionado el rendimiento, pero ¿qué pasa con la comodidad? La principal ventaja es que BufferedReader
puede leer datos no solo de un carácter a la vez (aunque read()
también tiene un método para este propósito), ¡sino también líneas enteras! Esto se hace usando readLine()
;
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("Leemos esta línea del teclado:");
System.out.println(s);
}
}
Salida de consola:
¡JavaRush es el mejor sitio para aprender Java!
Мы считали с клавиатуры эту строку:
JavaRush — лучший сайт для изучения Java!
Esto es especialmente útil cuando se lee una gran cantidad de datos. Aún se pueden leer una o dos líneas de texto carácter por carácter. Pero contar "Guerra y paz" una letra a la vez será algo problemático :) Ahora el trabajo de los hilos se ha vuelto mucho más claro para ti. Para más estudios, aquí hay una fuente adicional para usted:
Aquí puede leer más sobre los flujos entrantes y salientes. Reseña en vídeo BufferedReader
de uno de nuestros estudiantes. Sí, sí, ¡nuestros estudiantes no solo aprenden por sí mismos, sino que también graban videos educativos para otros! No olvides darle me gusta y suscribirte a nuestro canal :)
- BufferedReader/InputStreamReader : una de las conferencias de JavaRush dedicadas
BufferedReader
yInputStreamReader
- Lector de corriente de entrada de clase
- Class BufferedReader : documentación de Oracle sobre clases
BufferedReader
yInputStreamReader
.
GO TO FULL VERSION