Tarea 16: Añadir Objetos a un Fichero Existente con MiObjectOutputStream

Explicación del Ejercicio

En esta tarea se añaden dos alumnos más a alumnos.dat sin perder los ya guardados. El problema es que ObjectOutputStream escribe siempre una cabecera al crearse; si se abre el fichero en modo añadir, esa cabecera se escribe de nuevo en mitad del fichero y la lectura posterior falla. La solución es una subclase propia que no la escriba.

Conceptos y métodos clave:

  • Subclase MiObjectOutputStream: Hereda de ObjectOutputStream y redefine writeStreamHeader() con un cuerpo vacío, de forma que no se escribe ninguna cabecera.
  • Modo añadir (new FileOutputStream(fichero, true)): El segundo parámetro evita que el fichero se sobrescriba y coloca la escritura al final.
  • Variable existe: Se guarda el resultado de exists() antes de abrir el flujo, porque al abrir un FileOutputStream el fichero se crea y la comprobación posterior siempre daría true.
  • Elección del flujo: Si el fichero ya existía se usa MiObjectOutputStream; si no, un ObjectOutputStream normal que sí escribe la cabecera.
  • Comprobación: Al final se lee el fichero completo con ObjectInputStream y aparecen los 7 alumnos: los 5 originales y los 2 nuevos.

Código Fuente y Salida

MiObjectOutputStream.java
package ClaseFile;

import java.io.IOException;
import java.io.ObjectOutputStream;
import java.io.OutputStream;

/**
 * @author Eva Gallardo Romero
 * @date 29 de sep de 2026
 * Subclase de ObjectOutputStream que no escribe la cabecera del fichero.
 * Se usa para añadir objetos a un fichero que ya tiene cabecera.
 */
public class MiObjectOutputStream extends ObjectOutputStream {

    public MiObjectOutputStream(OutputStream out) throws IOException {
        super(out);
    }

    protected MiObjectOutputStream() throws IOException, SecurityException {
        super();
    }

    // redefino el método para que no escriba la cabecera
    @Override
    protected void writeStreamHeader() throws IOException {
    }
}
Clase15.java
package ClaseFile;

import java.io.EOFException;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;

/**
 * @author Eva Gallardo Romero
 * @date 29 de sep de 2026
 * Añadir dos alumnos más al final del fichero "alumnos.dat" sin perder los
 * que ya estaban guardados. Si el fichero ya existe hay que usar la clase
 * MiObjectOutputStream para que no se escriba otra cabecera. Después se
 * lee el fichero completo para comprobar que se han añadido.
 */
public class Clase15 {

    public static void main(String[] args) {

        // objeto File del fichero de objetos
        File fichero = new File("alumnos.dat");

        // guardo si existe ANTES de abrir el flujo, porque al abrirlo se crea
        boolean existe = fichero.exists();

        // alumnos nuevos que quiero añadir
        Alumno[] nuevos = {new Alumno("Pablo", 24, 7.0), new Alumno("Sara", 21, 9.5)};

        try (FileOutputStream fos = new FileOutputStream(fichero, true)) {

            // si el fichero existe no puedo escribir otra cabecera
            ObjectOutputStream oos;
            if (existe) {
                oos = new MiObjectOutputStream(fos);
            } else {
                oos = new ObjectOutputStream(fos);
            }

            for (int i = 0; i < nuevos.length; i++) {
                oos.writeObject(nuevos[i]);
                System.out.println("Añadido el alumno: " + nuevos[i].getNombre());
            }

            oos.close();

        } catch (IOException e) {
            System.out.println("Error al añadir los objetos: " + e.getMessage());
            return;
        }

        // leo el fichero completo para comprobar el resultado
        System.out.println("\nContenido actual de " + fichero.getName() + ":");
        try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream(fichero))) {

            try {
                while (true) {
                    Alumno alumno = (Alumno) ois.readObject();
                    System.out.printf("Nombre: %s, edad: %d, nota: %.2f %n",
                            alumno.getNombre(), alumno.getEdad(), alumno.getNota());
                }
            } catch (EOFException eof) {
                System.out.println("FIN DE LECTURA");
            }

        } catch (IOException | ClassNotFoundException e) {
            System.out.println("Error al leer los objetos: " + e.getMessage());
        }
    }
}

Resultado Mostrado por Terminal

Salida de Consola
Añadido el alumno: Pablo Añadido el alumno: Sara Contenido actual de alumnos.dat: Nombre: Lucía, edad: 20, nota: 8.50 Nombre: Carlos, edad: 22, nota: 6.00 Nombre: Marta, edad: 21, nota: 9.25 Nombre: Javier, edad: 23, nota: 7.50 Nombre: Elena, edad: 20, nota: 5.75 Nombre: Pablo, edad: 24, nota: 7.00 Nombre: Sara, edad: 21, nota: 9.50 FIN DE LECTURA