Entrada y Salida (I/O) de datos con Streams

Avanzado

Desde el comienzo de este curso, ha estado utilizando partes del sistema de E/S (Entrada y Salida) de Java, como println(). Sin embargo, lo has estado haciendo sin mucha explicación formal.

Debido a que el sistema de E/S de Java se basa en una jerarquía de clases, no fue posible presentar su teoría y detalles sin antes discutir las clases, la herencia y las excepciones. Ahora es el momento de examinar el enfoque de Java para E/S en detalle.

Esté prevenido, el sistema de E/S de Java es bastante grande y contiene muchas clases, interfaces y métodos. Parte de la razón de su tamaño es que Java define dos sistemas de E/S completos: uno para E/S de bytes y el otro para E/S de caracteres.

Este artículo le presentará muchas características importantes y de uso común. Afortunadamente, el sistema de E/S de Java es coherente y consistente; una vez que comprenda sus fundamentos, el resto del sistema de E/S es fácil de dominar.

Las clases de E/S descritas aquí son compatibles con E/S de consola basadas en texto y E/S de archivos. No se usan para crear interfaces gráficas de usuario (GUI). Por lo tanto, no los usará para crear aplicaciones con ventana, por ejemplo. Sin embargo, Java sí incluye soporte sustancial para construir interfaces gráficas de usuario. Los conceptos básicos de la programación de GUI se encuentran más adelante en Java Avanzado, que ofrece una introducción a Swing, y también una descripción general de JavaFX. (Swing y JavaFX son dos de los juegos de herramientas GUI de Java).

1. La E/S de Java se basa en flujos

Los programas Java realizan E/S a través de streams. Un flujo o stream de E/S es una abstracción que produce o consume información. Un stream está vinculada a un dispositivo físico por el sistema de E/ de Java. Todas las secuencias se comportan de la misma manera, incluso si difieren los dispositivos físicos reales a los que están vinculados. Por lo tanto, las mismas clases y métodos de E/S se pueden aplicar a diferentes tipos de dispositivos.

Por ejemplo, los mismos métodos que usa para escribir en la consola también se pueden usar para escribir en un archivo de disco. Java implementa flujos de E/S dentro de las jerarquías de clases definidas en el paquete java.io.

2. Byte Streams y Character Streams

Las versiones modernas de Java definen dos tipos de flujos de E/S: byte y carácter. (La versión original de Java definió solo el stream de bytes, pero los streams de caracteres se agregaron rápidamente).

  • Los streams de bytes proporcionan un medio conveniente para manejar la entrada y salida de bytes. Se usan, por ejemplo, al leer o escribir datos binarios. Son especialmente útiles cuando se trabaja con archivos.
  • Los streams de caracteres están diseñadas para manejar la entrada y salida de caracteres. Usan Unicode y, por lo tanto, pueden ser internacionalizados. Además, en algunos casos, los streams de caracteres son más eficientes que las secuencias de bytes.

El hecho de que Java defina dos tipos diferentes de flujos hace que el sistema de E/S sea bastante grande porque se necesitan dos conjuntos separados de jerarquías de clase (una para bytes y otra para caracteres). El gran número de clases de E/S puede hacer que el sistema de E/S sea más intimidante de lo que realmente es. Recuerde que, en su mayor parte, la funcionalidad de los streams de bytes es paralela a la de los  streams de caracteres.

Otro punto: en el nivel más bajo, todas las E/S todavía están orientadas a bytes. Los streams basados en caracteres simplemente proporcionan un medio conveniente y eficiente para manejar caracteres.
Lectura Recomendada
Streams de Bytes
Lectura Recomendada
Streams de Caracteres

3. Las clases stream de bytes

Los flujos de bytes se definen mediante el uso de dos jerarquías de clase. En la parte superior de estas hay dos clases abstractas: InputStream y OutputStream. InputStream define las características comunes a los flujos de entrada de bytes y OutputStream describe el comportamiento de los flujos de salida de bytes.

Desde InputStream y OutputStream se crean varias subclases concretas que ofrecen una funcionalidad variable y manejan los detalles de lectura y escritura en varios dispositivos, como archivos de disco. Las clases de flujo de bytes en java.io se muestran en la siguiente tabla.

No se sienta abrumado por la cantidad de clases diferentes. Una vez que puede usar un flujo de bytes, los otros son fáciles de dominar.
Tabla de las clases stream de bytes
Clases de flujo de bytesSignificado
BufferedInputStreamContiene métodos para leer bytes del búfer (área de memoria).
BufferedOutputStreamContiene métodos para escribir bytes en el búfer.
ByteArrayInputStreamContiene métodos para leer bytes de un array de bytes
ByteArrayOutputStreamContiene métodos para escribir bytes en un array de bytes.
DataInputStreamContiene métodos para leer tipos de datos primitivos de Java.
DataOutputStreamContiene métodos para escribir tipos de datos primitivos de Java.
FileInputStreamContiene métodos para leer bytes de un archivo.
FileOutputStreamContiene métodos para escribir bytes en un archivo.
FilterInputStreamContiene métodos para leer bytes de otros flujos de entrada que utiliza como fuente básica de datos.
FilterOutputStreamContiene métodos para escribir en otros flujos de salida.
InputStreamClase abstracta que describe la entrada del stream.
Output StreamClase abstracta que describe la salida del stream.
ObjectInputStreamContiene métodos para leer objetos.
ObjectOutputStreamContiene métodos para escribir objetos.
PipedInputStreamUn flujo de entrada canalizado debe conectarse a un flujo de salida canalizado.
PipedOutputStreamContiene métodos para escribir en un flujo de salida canalizado.
PrintStreamFlujo de salida que contiene print() y println()
PushbackInputStreamFlujo de entrada que permite que los bytes se devuelvan al stream.
SequenceInputStreamContiene métodos para concatenar múltiples flujos de entrada y luego leer de el flujo combinado.

4. Las clases stream de caracteres

Los flujos de caracteres se definen utilizando dos jerarquías de clase encabezadas por estas dos clases abstractas: Reader y Writer. Reader se usa como entrada y Writer se usa para la salida. Las clases concretas derivadas de Reader y Writer operan en flujos de caracteres Unicode.

De Reader y Writer derivan varias subclases concretas que manejan diversas situaciones de E/S. En general, las clases basadas en caracteres son paralelas a las clases basadas en bytes. Las clases de flujo de caracteres en java.io se muestran en la siguiente tabla:

Tabla de clases streams de caracteres.
Clases de flujo de caracteresSignificado
BufferedReaderContiene métodos para leer caracteres en un búfer.
BufferedWriterContiene métodos para escribir caracteres en un búfer.
CharArrayReaderContiene métodos para leer caracteres de una matriz de caracteres.
CharArrayWriterContiene métodos para escribir caracteres en una matriz de caracteres.
FileReaderContiene métodos para leer desde un archivo.
FileWriterContiene métodos para escribir en un archivo.
FilterReaderContiene métodos para leer caracteres en el flujo de entrada subyacente.
FilterWriterContiene métodos para escribir caracteres en el flujo de salida subyacente
InputStreamReaderContiene métodos para convertir bytes en caracteres.
LineNumberReaderFlujo de entrada que cuenta las líneas.
OutputStreamWriterContiene métodos para convertir de caracteres a bytes.
PipedReaderPipe de entrada.
PipedWriterPipe de salida.
PushbackReaderFlujo de entrada que permite que los caracteres se devuelvan al flujo de entrada.
ReaderClase abstracta que describe la entrada de flujo de caracteres.
WriterClase abstracta que describe la salida de flujo de caracteres.
StringReaderContiene métodos para leer en una cadena.
StringWriterContiene métodos para escribir en una cadena.

5. Los flujos predefinidos

Como sabes, todos los programas Java importan automáticamente el paquete java.lang. Este paquete define una clase llamada System, que encapsula varios aspectos del entorno de tiempo de ejecución. Entre otras cosas, contiene tres variables de flujo predefinidas, llamadas in, out y err. Estos campos se declaran como públicos (public), finales (final) y estáticos (static) dentro de System. Esto significa que pueden ser utilizados por cualquier otra parte de tu programa y sin referencia a un objeto específico de System.

System.out se refiere a la secuencia de salida estándar. Por defecto, esta es la consola. System.in se refiere a la entrada estándar, que es por defecto el teclado. System.err se refiere a la secuencia de error estándar, que también es la consola por defecto. Sin embargo, estas secuencias se pueden redireccionar a cualquier dispositivo de E/S compatible.

System.in es un objeto de tipo InputStream; System.out y System.err son objetos del tipo PrintStream. Se trata de flujos de bytes, aunque normalmente se utilizan para leer y escribir caracteres desde y hacia la consola. La razón por la que son bytes y no flujos de caracteres es que los flujos predefinidos eran parte de la especificación original para Java, que no incluía los streams de caracteres. Como verás, es posible ajustarlos dentro de streams basadas en caracteres si lo desea.

E/S en Java
  • Uso de Streams

Sobre el Autor:

Hey hola! Yo soy Alex Walton y tengo el placer de compartir conocimientos hacía ti sobre el tema de Programación en Java, desde cero, Online y Gratis.

Deja una Respuesta

*

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.