Tarea 19: Acceso Aleatorio: Consultar, Añadir, Insertar y Modificar Registros

Explicación del Ejercicio

Esta tarea aprovecha la principal ventaja del acceso aleatorio: llegar directamente a cualquier registro calculando su posición a partir del identificador, sin leer los anteriores. Trabaja sobre el fichero empleados.dat de la Tarea 17 y se divide en métodos estáticos para no repetir código.

Conceptos y métodos clave:

  • Constante TAM: Guarda el tamaño del registro (36 bytes) para usarlo en todos los cálculos de posición.
  • Consultar: La posición del registro es (id - 1) * TAM. Si es mayor o igual que file.length(), el empleado no existe (caso del id 15).
  • Añadir: La posición de escritura es el propio file.length(), es decir, justo detrás del último registro.
  • Insertar: Se escribe en (id - 1) * TAM. Con el id 10 la posición queda más allá del final, así que el fichero crece y el registro 9 queda como un hueco lleno de ceros, que leerRegistro() ignora por tener id 0.
  • Modificar: Para cambiar solo el departamento y el salario se suma 4 + 20 a la posición, saltando el id (4 bytes) y el apellido (20 bytes), y se escriben únicamente esos dos campos.
  • Listado final: Se recorre todo el fichero de 36 en 36 bytes mostrando el resultado de todas las operaciones.

Código Fuente y Salida

Clase18.java
package ClaseFile;

import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;

/**
 * @author Eva Gallardo Romero
 * @date 30 de sep de 2026
 * Sobre el fichero "empleados.dat" (registros de 36 bytes) realizar:
 * - Consultar un empleado por su identificador
 * - Añadir un empleado al final del fichero
 * - Insertar un empleado en la posición que le corresponde por su id
 * - Modificar el departamento y el salario de un empleado
 * Al final se muestra el contenido completo del fichero.
 */
public class Clase18 {

    // tamaño en bytes de cada registro
    static final int TAM = 36;

    public static void main(String[] args) {

        File fichero = new File("empleados.dat");

        if (!fichero.exists()) {
            System.out.println("El fichero no existe: " + fichero.getName());
            return;
        }

        try (RandomAccessFile file = new RandomAccessFile(fichero, "rw")) {

            // consulto un empleado que existe y otro que no
            consultar(file, 5);
            consultar(file, 15);

            // añado un empleado al final: su posición es el tamaño del fichero
            System.out.println("\nAñado el empleado 8 al final del fichero");
            escribir(file, file.length(), 8, "CASTILLO", 20, 1675.40);

            // inserto un empleado con id 10: su posición es (id - 1) * 36
            System.out.println("Inserto el empleado 10 en su posición");
            escribir(file, (10 - 1) * TAM, 10, "GONZALEZ", 10, 1230.87);

            // modifico el departamento y salario del empleado 4
            System.out.println("Modifico el departamento y el salario del empleado 4\n");
            modificar(file, 4, 40, 4000.87);

            // muestro todo el contenido del fichero
            listar(file);

        } catch (IOException e) {
            System.out.println("Error de E/S: " + e.getMessage());
        }
    }

    // consulta un empleado calculando su posición con el identificador
    static void consultar(RandomAccessFile file, int id) throws IOException {

        long posicion = (id - 1) * TAM;

        if (posicion >= file.length()) {
            System.out.printf("ID: %d, NO EXISTE EMPLEADO %n", id);
        } else {
            file.seek(posicion);
            leerRegistro(file);
        }
    }

    // escribe un registro completo a partir de una posición
    static void escribir(RandomAccessFile file, long posicion, int id, String apellido, int dep, double salario)
            throws IOException {

        file.seek(posicion);
        file.writeInt(id);

        StringBuffer buffer = new StringBuffer(apellido);
        buffer.setLength(10);
        file.writeChars(buffer.toString());

        file.writeInt(dep);
        file.writeDouble(salario);
    }

    // modifica solo dep y salario: salto id (4 bytes) y apellido (20 bytes)
    static void modificar(RandomAccessFile file, int id, int dep, double salario) throws IOException {

        long posicion = (id - 1) * TAM + 4 + 20;

        file.seek(posicion);
        file.writeInt(dep);
        file.writeDouble(salario);
    }

    // lee el registro que hay en la posición actual y lo muestra
    static void leerRegistro(RandomAccessFile file) throws IOException {

        char[] apellido = new char[10];

        int id = file.readInt();
        for (int i = 0; i < apellido.length; i++) {
            apellido[i] = file.readChar();
        }
        int dep = file.readInt();
        double salario = file.readDouble();

        if (id > 0) {
            System.out.printf("ID: %d, Apellido: %s, Departamento: %d, Salario: %.2f %n",
                    id, new String(apellido).trim(), dep, salario);
        }
    }

    // recorre el fichero completo registro a registro
    static void listar(RandomAccessFile file) throws IOException {

        System.out.println("Contenido final del fichero:");

        for (long posicion = 0; posicion < file.length(); posicion = posicion + TAM) {
            file.seek(posicion);
            leerRegistro(file);
        }
    }
}

Resultado Mostrado por Terminal

Salida de Consola
ID: 5, Apellido: ROMERO, Departamento: 20, Salario: 1950.25 ID: 15, NO EXISTE EMPLEADO Añado el empleado 8 al final del fichero Inserto el empleado 10 en su posición Modifico el departamento y el salario del empleado 4 Contenido final del fichero: ID: 1, Apellido: MARTIN, Departamento: 10, Salario: 1250.50 ID: 2, Apellido: PEREZ, Departamento: 20, Salario: 1800.00 ID: 3, Apellido: SANCHEZ, Departamento: 10, Salario: 1500.75 ID: 4, Apellido: DIAZ, Departamento: 40, Salario: 4000.87 ID: 5, Apellido: ROMERO, Departamento: 20, Salario: 1950.25 ID: 6, Apellido: NAVARRO, Departamento: 30, Salario: 1400.00 ID: 7, Apellido: IGLESIAS, Departamento: 10, Salario: 2300.90 ID: 8, Apellido: CASTILLO, Departamento: 20, Salario: 1675.40 ID: 10, Apellido: GONZALEZ, Departamento: 10, Salario: 1230.87