Esta es la contestación más acertada que te podemos aportar, pero primero estúdiala detenidamente y valora si se adapta a tu trabajo.
Solución:
Este enlace de conceptos y uso de Streams in Java ofrece explicaciones muy interesantes.
Streams, Readers, Writers, BufferedReader, BufferedWriter: estas son las terminologías con las que tratará en Java. Existen las clases proporcionadas en Java para operar con entrada y salida. Realmente vale la pena saber cómo se relacionan y cómo se usa. Esta publicación explorará los Streams en Java y otras clases relacionadas en detalle. Así que comencemos:
Definamos cada uno de estos en alto nivel y luego profundicemos.
Corrientes
Se utiliza para tratar con datos a nivel de bytes.
Lector / Escritor
Se usa para lidiar con el nivel del personaje. También admite varias codificaciones de caracteres.
BufferedReader / BufferedWriter
Para aumentar el rendimiento. Los datos que se leerán se almacenarán en la memoria para un acceso rápido.
Si bien estos son para tomar entradas, solo existen las clases correspondientes para la salida. Por ejemplo, si hay un InputStream que está destinado a leer el flujo de bytes, OutputStream ayudará a escribir el flujo de bytes.
InputStreams
Hay muchos tipos de InputStreams que proporciona java. Cada uno se conecta a distintas fuentes de datos, como byte array, Archivo, etc.
Por ejemplo, FileInputStream se conecta a una fuente de datos de archivo y podría usarse para leer bytes de un archivo. Si bien ByteArrayInputStream podría usarse para tratar bytes array como flujo de entrada.
Flujo de salida
Esto ayuda a escribir bytes en una fuente de datos. Para casi todos los InputStream hay un OutputStream correspondiente, siempre que tenga sentido.
ACTUALIZAR
¿Qué es la transmisión en búfer?
Aquí estoy citando de Buffered Streams, documentación de Java (con una explicación técnica):
Secuencias almacenadas en búfer
La mayoría de los ejemplos que hemos visto hasta ahora utilizan E / S sin búfer. Esto significa que cada solicitud de lectura o escritura es manejada directamente por el sistema operativo subyacente. Esto puede hacer que un programa sea mucho menos eficiente, ya que cada una de estas solicitudes a menudo desencadena el acceso al disco, la actividad de la red o alguna otra operación que es relativamente costosa.
Para reducir este tipo de sobrecarga, la plataforma Java implementa flujos de E / S almacenados en búfer. Los flujos de entrada almacenados en búfer leen datos de un área de memoria conocida como búfer; la API de entrada nativa se llama solo cuando el búfer está vacío. De manera similar, los flujos de salida almacenados en búfer escriben datos en un búfer y la API de salida nativa se llama solo cuando el búfer está lleno.
A veces pierdo el pelo leyendo una documentación técnica. Entonces, aquí cito la explicación más humana de https://yfain.github.io/Java4Kids/:
En general, el acceso al disco es mucho más lento que el procesamiento realizado en la memoria; por eso no es buena idea acceder al disco mil veces para leer un archivo de 1000 bytes. Para minimizar el número de veces que se accede al disco, Java proporciona búferes, que sirven como depósitos de datos.
Al leer File con FileInputStream y luego BufferedInputStream, la clase BufferedInputStream funciona como intermediario entre FileInputStream y el archivo en sí. Lee una gran cantidad de bytes de un archivo a la memoria (un búfer) de una sola vez, y el objeto FileInputStream luego lee bytes individuales desde allí, que son operaciones rápidas de memoria a memoria. BufferedOutputStream funciona de manera similar con la clase FileOutputStream.
La idea principal aquí es minimizar el acceso al disco. Las transmisiones almacenadas en búfer no cambian el tipo de las transmisiones originales, solo hacen que la lectura sea más eficiente. Un programa realiza el encadenamiento de arroyos (o tuberías de arroyos) para conectar arroyos, al igual que las tuberías se conectan en las tuberías.
InputStream, OutputStream, byte[], ByteBuffer
son para binario datos.-
Reader, Writer, String, char
son para texto, internamente Unicode, de modo que se puedan combinar todos los scripts del mundo (por ejemplo, griego y árabe). -
InputStreamReader
yOutputStreamWriter
forman un puente entre ambos. Si tiene InputStream y sabe que sus bytes son en realidad texto en alguna codificación, Charset, entonces puede envolver el InputStream:try (InputStreamReader reader = new InputStreamReader(stream, StandardCharsets.UTF_8)) ... read text ...
Hay un constructor sin Charset, pero que no es portátil, ya que usa la codificación de plataforma predeterminada.
En Android StandardCharset puede no existir, use “UTF-8”.
Las clases derivadas FileInputStream
y BufferedReader
agregar algo a los padres InputStream
resp. Reader
.
Un FileInputStream es para la entrada de un Archivo, y BufferedReader usa un búfer de memoria, por lo que la lectura física real no lee los caracteres (ineficaz). Con new BufferedReader(otherReader)
agrega almacenamiento en búfer a su lector original.
Entendido todo esto, existe la clase de utilidad Files
con métodos como newBufferedReader(Path, Charset)
que agregan brevedad adicional.
Al final de la post puedes encontrar las explicaciones de otros sys admins, tú también eres capaz insertar el tuyo si te apetece.