Título: Serialización de Objetos en Java

Introducción

La serialización es una técnica en Java que permite convertir un objeto en una secuencia de bytes para su almacenamiento o transmisión. Esto es útil para guardar el estado de un objeto en un archivo o para enviarlo a través de una red. Posteriormente, mediante la deserialización, se puede reconstruir el objeto a partir de estos bytes. En este artículo, explicaremos en detalle cómo funciona la serialización de objetos en Java y cómo utilizarla en la práctica con ejemplos.

Conceptos clave de la serialización

  • Serialización: El proceso de convertir un objeto en una secuencia de bytes para que pueda ser almacenado o transmitido.
  • Deserialización: El proceso inverso, donde los bytes almacenados o transmitidos se convierten de nuevo en un objeto.
  • Interfaz Serializable: Un objeto debe implementar esta interfaz para ser serializable. No requiere la implementación de métodos, solo sirve para marcar que un objeto es apto para la serialización.

Ejemplo básico de serialización

Imaginemos que tenemos una clase Persona que queremos serializar. Para ello, esta clase debe implementar la interfaz Serializable.

import java.io.Serializable;

public class Persona implements Serializable {
    private String nombre;
    private String telefono;
    private String email;
    private String nacimiento;

    public Persona(String nombre, String telefono, String email, String nacimiento) {
        this.nombre = nombre;
        this.telefono = telefono;
        this.email = email;
        this.nacimiento = nacimiento;
    }

    @Override
    public String toString() {
        return "Nombre: " + nombre + ", Teléfono: " + telefono + ", Email: " + email + ", Nacimiento: " + nacimiento;
    }
}

Serialización de un objeto

Para serializar un objeto, utilizamos la clase ObjectOutputStream, que nos permite escribir objetos en un archivo de manera binaria.

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;

public class SerializarObjeto {
    public static void main(String[] args) {
        Persona persona = new Persona("Juan", "123456789", "juan@gmail.com", "01/01/1990");

        try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("persona.dat"))) {
            oos.writeObject(persona);
            System.out.println("Objeto serializado con éxito.");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

Explicación del código:

  • ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("persona.dat"));: Crea un flujo para escribir el objeto persona en un archivo llamado «persona.dat».
  • oos.writeObject(persona);: Serializa el objeto persona y lo guarda en el archivo.
  • El flujo se cierra automáticamente al final gracias al bloque try-with-resources.

Deserialización de un objeto

Para leer un objeto serializado de un archivo, utilizamos la clase ObjectInputStream, que nos permite reconstruir el objeto desde el archivo binario.

import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;

public class DeserializarObjeto {
    public static void main(String[] args) {
        try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream("persona.dat"))) {
            Persona persona = (Persona) ois.readObject();
            System.out.println("Objeto deserializado con éxito: " + persona);
        } catch (IOException | ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
}

Explicación del código:

  • ObjectInputStream ois = new ObjectInputStream(new FileInputStream("persona.dat"));: Abre el archivo «persona.dat» para leer el objeto almacenado.
  • Persona persona = (Persona) ois.readObject();: Deserializa el objeto del archivo y lo convierte de nuevo a un objeto de tipo Persona.
  • Se maneja la excepción ClassNotFoundException porque readObject() requiere que la clase del objeto deserializado esté disponible en el programa.

Problema común: Múltiples cabeceras en el archivo

Cuando escribimos varios objetos en un archivo usando ObjectOutputStream, se añade una cabecera de metadatos para cada objeto. Si se vuelve a abrir el archivo para añadir más objetos, esta cabecera adicional puede generar una excepción StreamCorruptedException cuando intentamos leer los objetos.

Solución: Redefinir ObjectOutputStream

Una solución para evitar el problema de las cabeceras adicionales es redefinir la clase ObjectOutputStream y sobreescribir el método writeStreamHeader() para que no se escriba una nueva cabecera.

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;

class MiObjectOutputStream extends ObjectOutputStream {
    public MiObjectOutputStream(FileOutputStream fos) throws IOException {
        super(fos);
    }

    @Override
    protected void writeStreamHeader() throws IOException {
        // No hacer nada para evitar escribir una nueva cabecera
    }
}

Uso de la clase redefinida:

import java.io.FileOutputStream;
import java.io.IOException;

public class SerializarMultiplesObjetos {
    public static void main(String[] args) {
        Persona persona1 = new Persona("Ana", "987654321", "ana@gmail.com", "02/02/1992");
        Persona persona2 = new Persona("Luis", "112233445", "luis@gmail.com", "03/03/1993");

        try (FileOutputStream fos = new FileOutputStream("personas.dat");
             ObjectOutputStream oos = new ObjectOutputStream(fos)) {
            oos.writeObject(persona1);
        } catch (IOException e) {
            e.printStackTrace();
        }

        try (FileOutputStream fos = new FileOutputStream("personas.dat", true);
             MiObjectOutputStream oos = new MiObjectOutputStream(fos)) {
            oos.writeObject(persona2);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

Explicación del código:

  • En la primera escritura, usamos el ObjectOutputStream normal para añadir la cabecera.
  • En las escrituras posteriores, usamos nuestra clase redefinida MiObjectOutputStream para evitar que se añadan cabeceras adicionales.

Conclusión

La serialización de objetos en Java es una herramienta poderosa para almacenar y transmitir objetos. Nos permite convertir un objeto en una secuencia de bytes, almacenarlo en un archivo y reconstruirlo más tarde mediante la deserialización. Es fundamental tener en cuenta los posibles problemas con las cabeceras cuando se manejan múltiples objetos en un archivo, y la solución presentada ofrece una forma efectiva de gestionar este escenario.

Gracias por visitar mi blog de informática, mi nombre es Tomás y soy formador y desarrollador web. Si quiere usted dejarme alguna sugerencia, ayuda o quiere un servicio de formación estoy escuchando ofertas en tomas.gonzalez@infogonzalez.com, en Facebook a https://www.facebook.com/Infogonzalez estoy deseando escucharle. Su duda o sugerencia NO molesta.

Deja un comentario

Información básica sobre protección de datos Ver más

  • Responsable: Tomas Gonzalez.
  • Finalidad:  Moderar los comentarios.
  • Legitimación:  Por consentimiento del interesado.
  • Destinatarios y encargados de tratamiento:  No se ceden o comunican datos a terceros para prestar este servicio.
  • Derechos: Acceder, rectificar y suprimir los datos.
  • Información Adicional: Puede consultar la información detallada en la Política de Privacidad.

error: Content is protected !!

Descubre más desde InfoGonzalez - Blog de formador e informático

Suscríbete ahora para seguir leyendo y obtener acceso al archivo completo.

Seguir leyendo

Este sitio web utiliza cookies, si necesitas más información puedes visitar nuestra política de privacidad    Ver
Privacidad