Introducción
Los flujos de bytes en Java son fundamentales para el manejo de datos binarios en archivos. A diferencia de los flujos de caracteres, que trabajan con datos de 16 bits (Unicode), los flujos de bytes trabajan con datos de 8 bits, permitiendo la lectura y escritura de cualquier tipo de datos, incluidos archivos binarios como imágenes, videos, y ficheros comprimidos. Este artículo explica cómo funcionan los flujos de bytes y cómo utilizarlos con ejemplos prácticos en Java.
Flujos de Bytes en Java
Los flujos de bytes se utilizan principalmente para realizar operaciones de entrada y salida de datos binarios. Las clases más importantes en este ámbito son:
InputStream
yOutputStream
: Clases abstractas que proporcionan la funcionalidad básica para leer y escribir bytes.FileInputStream
yFileOutputStream
: Clases específicas para manejar flujos de bytes desde y hacia archivos binarios.DataInputStream
yDataOutputStream
: Clases que permiten leer y escribir datos de tipos primitivos (int, float, etc.) en forma de bytes.
Lectura de ficheros binarios con FileInputStream
La clase FileInputStream
se utiliza para leer archivos binarios. A través de esta clase, se pueden leer datos byte por byte o en bloques, almacenándolos en un array de bytes.
Ejemplo 1: Leer un fichero binario con FileInputStream
import java.io.FileInputStream;
import java.io.IOException;
public class LeerFicheroBinario {
public static void main(String[] args) {
try (FileInputStream fis = new FileInputStream("archivo.dat")) {
int byteLeido;
// Leer byte por byte hasta el final del fichero
while ((byteLeido = fis.read()) != -1) {
System.out.print(byteLeido + " ");
}
} catch (IOException e) {
System.out.println("Error al leer el fichero: " + e.getMessage());
}
}
}
Explicación del código:
FileInputStream fis = new FileInputStream("archivo.dat");
: Se abre el fichero binario «archivo.dat» para su lectura.fis.read()
: Lee un byte del fichero. Devuelve-1
cuando se alcanza el final.- El flujo se cierra automáticamente gracias al bloque
try-with-resources
.
Escritura de ficheros binarios con FileOutputStream
La clase FileOutputStream
permite escribir datos binarios en un archivo. Es útil para crear o modificar archivos binarios y guardar datos como imágenes o videos.
Ejemplo 2: Escribir en un fichero binario con FileOutputStream
import java.io.FileOutputStream;
import java.io.IOException;
public class EscribirFicheroBinario {
public static void main(String[] args) {
try (FileOutputStream fos = new FileOutputStream("archivo.dat")) {
byte[] datos = {10, 20, 30, 40, 50};
fos.write(datos);
} catch (IOException e) {
System.out.println("Error al escribir en el fichero: " + e.getMessage());
}
}
}
Explicación del código:
FileOutputStream fos = new FileOutputStream("archivo.dat");
: Crea un fichero binario «archivo.dat» para escribir en él.fos.write(datos);
: Escribe el array de bytes en el fichero.- El flujo se cierra automáticamente gracias al bloque
try-with-resources
.
Lectura y escritura de tipos primitivos con DataInputStream y DataOutputStream
Las clases DataInputStream
y DataOutputStream
permiten leer y escribir tipos de datos primitivos (int, float, etc.) en forma de bytes. Esto es útil cuando se necesita almacenar datos estructurados en un archivo binario.
Ejemplo 3: Escribir y leer datos primitivos en un fichero binario
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class EscribirLeerPrimitivos {
public static void main(String[] args) {
// Escribir datos primitivos en el fichero
try (DataOutputStream dos = new DataOutputStream(new FileOutputStream("datos.dat"))) {
dos.writeInt(100);
dos.writeDouble(45.67);
dos.writeBoolean(true);
} catch (IOException e) {
System.out.println("Error al escribir en el fichero: " + e.getMessage());
}
// Leer los datos primitivos del fichero
try (DataInputStream dis = new DataInputStream(new FileInputStream("datos.dat"))) {
int numero = dis.readInt();
double decimal = dis.readDouble();
boolean valorBooleano = dis.readBoolean();
System.out.println("Número: " + numero);
System.out.println("Decimal: " + decimal);
System.out.println("Booleano: " + valorBooleano);
} catch (IOException e) {
System.out.println("Error al leer el fichero: " + e.getMessage());
}
}
}
Explicación del código:
- Escritura: Se utilizan los métodos
writeInt()
,writeDouble()
, ywriteBoolean()
para escribir un entero, un número de punto flotante y un booleano, respectivamente, en el fichero binario. - Lectura: Los métodos
readInt()
,readDouble()
, yreadBoolean()
se utilizan para leer los datos en el mismo orden en que fueron escritos.
Manejo de Excepciones
El manejo adecuado de excepciones es crucial al trabajar con flujos de bytes, ya que las operaciones de E/S son propensas a fallar por diversas razones, como la falta de permisos de escritura o lectura, o la ausencia del fichero. Para ello, se deben manejar excepciones como IOException
y FileNotFoundException
.
Conclusión
El manejo de flujos de bytes en Java es esencial para trabajar con archivos binarios. Las clases FileInputStream
, FileOutputStream
, DataInputStream
y DataOutputStream
proporcionan las herramientas necesarias para leer y escribir datos binarios y tipos primitivos. Estos conceptos son la base para el desarrollo de aplicaciones que necesitan interactuar con archivos no textuales, como imágenes, videos y datos estructurados. Los ejemplos presentados muestran cómo implementar soluciones eficientes y robustas para gestionar este tipo de archivos en Java.