1. InputStreamReaderclase

Otra característica interesante de las secuencias es que puede combinar varias secuencias en cadenas . Una secuencia puede leer datos no solo de su fuente de datos interna, sino también de otra secuencia .

Este es un mecanismo muy poderoso en Java, que hace posible crear escenarios de lectura de datos complejos conectando un flujo con otro. Tal esquema se ve así:

Clase InputStreamReader

Cuando un programa lee datos de un flujo de datos, el flujo de datos a su vez lee los datos de su fuente de datos, que es otro flujo de datos o un archivo, por ejemplo.

Además, cada flujo de datos no solo lee y entrega datos, sino que también puede transformarlos o realizar varias operaciones en ellos. Un buen ejemplo de tal "flujo intermedio" es la InputStreamReaderclase.

Ya conocemos una clase llamada FileReader— es una Readerque lee datos de un archivo. ¿Y de dónde InputStreamReaderobtiene sus datos? Así es, desde un InputStream.

Cuando crea un InputStreamReaderobjeto, debe pasar un InputStreamobjeto o una de sus clases descendientes. Ejemplo:

String src = "c:\\projects\\log.txt";
FileInputStream input = new FileInputStream(src);
InputStreamReader reader = new InputStreamReader(input);

La InputStreamReaderclase tiene todos los métodos que Readertiene la clase y funcionan exactamente de la misma manera.

La principal diferencia entre la InputStreamReaderclase y, digamos, FileReaderes de dónde leen los datos. FileReaderlee datos de un archivo (duh, por eso se llama FileReader), pero InputStreamReaderlee datos de un archivo InputStream.

Cuando lee un carácter de un FileReaderobjeto usando el read()método, a su vez lee dos bytes del archivo en el disco y los devuelve como chars.

Cuando lee un carácter de un InputStreamReaderobjeto utilizando el read()método, a su vez lee dos bytes del FileInputStreamobjeto que se le pasa, que a su vez lee los datos del archivo. El resultado es una cadena de llamadas a read()métodos.


2. BufferedReaderclase

Otra clase interesante que probablemente usará mucho es BufferedReader. Este también es un "flujo intermedio" que lee datos de otro flujo.

Como sugiere su nombre, la BufferedReaderclase es una subclase de Readery le permite leer caracteres . Pero lo más interesante es que también hay que pasarle una fuente de datos en forma de stream desde el que se puedan leer los caracteres , es decir, un stream que herede la Readerclase.

¿Cuál es el punto de? A diferencia de InputStreamReader, la BufferedReaderclase no convierte bytes en caracteres: no convierte nada en absoluto. En su lugar, almacena datos en búfer .

Cuando un programa lee un solo carácter de un BufferedReaderobjeto, el objeto lee una gran variedad de caracteres de su flujo de origen, todos a la vez. Y los almacena internamente.

Cuando se lee el siguiente carácter del BufferedReaderobjeto, simplemente toma el siguiente carácter de su matriz de búfer interno y lo devuelve sin acceder a la fuente de datos. Solo cuando se agotan todos los caracteres del búfer, se lee otra gran matriz de caracteres.

La BufferedReaderclase también tiene un método muy útil: String readLine(), que le permite leer cadenas completas de datos del flujo de origen de una sola vez. Puede usar este método para, por ejemplo, leer un archivo y mostrar su contenido en la pantalla línea por línea. Ejemplo:

Específicamente escribimos un código compacto para ilustrar cuán conveniente puede ser esto. Este código también se podría escribir con un poco más de detalle.

String src = "c:\\projects\\log.txt";

try(FileReader in = new FileReader(src);
BufferedReader reader = new BufferedReader(in))
{
   while (reader.ready())
   {
      String line = reader.readLine();
      System.out.println(line);
   }
}
Crea un FileReaderobjeto. La fuente de datos es un archivo.
Crea un BufferedReaderobjeto. La fuente de datos es un FileReader.
Siempre que haya datos en el lector
Leer una línea
Mostrar la línea
Un punto importante:

Si encadena varios flujos, close()solo es necesario llamar al método en uno de ellos. Ese flujo llamará al método en su fuente de datos, y así sucesivamente, hasta que close()se llame al flujo de datos final.



3. Lectura desde la consola

Y un dato más interesante: la Scannerclase no es más que un flujo de entrada intermedio que lee datos de System.in, que también es un flujo de datos.

Aquí hay dos formas de leer una línea desde la consola:

Clase de escáner Clases BufferedReader y BufferedWriter
InputStream stream = System.in;
Scanner console = new Scanner(stream);
String line = console.nextLine();
InputStream stream = System.in;
InputStreamReader reader = new InputStreamReader(stream);
BufferedReader buff = new BufferedReader(reader);
String line = buff.readLine();

Nuestro amigo no es más que una variable estática de la clase. Es un cuyo nombre es .System.ininSystemInputStreamin

Entonces, casi desde el comienzo de sus estudios de Java en CodeGym, ha estado trabajando con flujos de datos y construyendo cadenas a partir de ellos. Pero ahora lo harás más conscientemente.