Jerarquia De Clases I O

Jerarquia de clases I/O

Entender la jerarquía de clases de I/O en Java es clave para trabajar con flujos de datos (streams). Aquí te explico y desarrollo los conceptos principales en Java, organizados de manera práctica para aprenderlos en contexto y adquirir un buen nivel.

Categoría Clase Abstracta Subclases Importantes Uso Principal
Byte Streams InputStream FileInputStream, BufferedInputStream, DataInputStream Lectura de datos binarios.
OutputStream FileOutputStream, BufferedOutputStream, DataOutputStream Escritura de datos binarios.
Character Streams Reader FileReader, BufferedReader Lectura de texto.
Writer FileWriter, BufferedWriter Escritura de texto.
Decoradores - BufferedInputStream, BufferedOutputStream Mejorar rendimiento mediante buffering.
Manejo de Primitivos - DataInputStream, DataOutputStream Lectura y escritura de datos primitivos.
Serialización - ObjectInputStream, ObjectOutputStream Almacenamiento y recuperación de objetos completos (serialización).

1. Jerarquía de Clases de I/O

En Java, las clases de I/O se dividen en dos grandes categorías según la dirección del flujo:

  • Entrada (Input): Para leer datos.
  • Salida (Output): Para escribir datos.

Además, estas clases se subdividen según el tipo de datos que manejan:

  • Byte Streams: Trabajan con datos binarios (InputStream y OutputStream).
  • Character Streams: Trabajan con texto (Reader y Writer).

2. Byte Streams

Estas clases operan con datos binarios (bytes) y son ideales para manejar archivos multimedia o cualquier dato que no sea texto.

Clases principales:

  • InputStream: Clase base para leer bytes.
    • Subclases: FileInputStream, BufferedInputStream, DataInputStream.
  • OutputStream: Clase base para escribir bytes.
    • Subclases: FileOutputStream, BufferedOutputStream, DataOutputStream.

Ejemplo: Copiar un archivo binario.

import java.io.*;

public class ByteStreamExample {
    public static void main(String[] args) {
        String sourceFile = "input.bin";
        String targetFile = "output.bin";

        try (InputStream inputStream = new FileInputStream(sourceFile);
             OutputStream outputStream = new FileOutputStream(targetFile)) {

            int byteData;
            while ((byteData = inputStream.read()) != -1) {
                outputStream.write(byteData);
            }
            System.out.println("Archivo copiado exitosamente.");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

3. Character Streams

Diseñadas para trabajar con texto, estas clases facilitan la lectura y escritura de caracteres Unicode.

Clases principales:

  • Reader: Clase base para leer caracteres.
    • Subclases: FileReader, BufferedReader.
  • Writer: Clase base para escribir caracteres.
    • Subclases: FileWriter, BufferedWriter.

Ejemplo: Copiar texto con BufferedReader y BufferedWriter.

import java.io.*;

public class CharacterStreamExample {
    public static void main(String[] args) {
        String sourceFile = "input.txt";
        String targetFile = "output.txt";

        try (BufferedReader reader = new BufferedReader(new FileReader(sourceFile));
             BufferedWriter writer = new BufferedWriter(new FileWriter(targetFile))) {

            String line;
            while ((line = reader.readLine()) != null) {
                writer.write(line);
                writer.newLine();
            }
            System.out.println("Texto copiado exitosamente.");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

4. Streams Decorados

El patrón Decorator permite agregar funcionalidades adicionales a los streams, como buffering.

Ejemplo: Uso de BufferedInputStream para optimizar lectura.

import java.io.*;

public class BufferedStreamExample {
    public static void main(String[] args) {
        String fileName = "largeFile.bin";

        try (InputStream inputStream = new BufferedInputStream(new FileInputStream(fileName))) {
            int byteData;
            while ((byteData = inputStream.read()) != -1) {
                // Procesar cada byte
            }
            System.out.println("Archivo leído con buffering.");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

5. Manejo de Datos Primitivos

Con DataInputStream y DataOutputStream, es posible leer y escribir datos primitivos directamente.

Ejemplo: Guardar y recuperar datos primitivos.

import java.io.*;

public class DataStreamExample {
    public static void main(String[] args) {
        String fileName = "data.bin";

        // Escribir datos primitivos
        try (DataOutputStream dos = new DataOutputStream(new FileOutputStream(fileName))) {
            dos.writeInt(123);
            dos.writeDouble(45.67);
            dos.writeUTF("Hola Mundo");
        } catch (IOException e) {
            e.printStackTrace();
        }

        // Leer datos primitivos
        try (DataInputStream dis = new DataInputStream(new FileInputStream(fileName))) {
            int intData = dis.readInt();
            double doubleData = dis.readDouble();
            String stringData = dis.readUTF();

            System.out.printf("Entero: %d, Doble: %.2f, Cadena: %s%n", intData, doubleData, stringData);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

6. Serialización

La serialización permite guardar objetos completos y recuperarlos posteriormente. Esto es útil para persistir datos en formato binario.

Ejemplo: Serializar y deserializar un objeto.

import java.io.*;

class Persona implements Serializable {
    private static final long serialVersionUID = 1L;
    private String nombre;
    private int edad;

    public Persona(String nombre, int edad) {
        this.nombre = nombre;
        this.edad = edad;
    }

    @Override
    public String toString() {
        return "Persona{" +
               "nombre='" + nombre + '\'' +
               ", edad=" + edad +
               '}';
    }
}

public class SerializationExample {
    public static void main(String[] args) {
        String fileName = "persona.ser";

        // Serializar objeto
        Persona persona = new Persona("Juan", 30);
        try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(fileName))) {
            oos.writeObject(persona);
        } catch (IOException e) {
            e.printStackTrace();
        }

        // Deserializar objeto
        try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream(fileName))) {
            Persona deserialized = (Persona) ois.readObject();
            System.out.println("Objeto deserializado: " + deserialized);
        } catch (IOException | ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
}