Java: serializando objetos para guardar y recuperar en ficheros (editado)

2017-05-01 - Categorías: Java
Logo de Java

Desenpolvando un poco temas de Java, hoy traigo un pequeño howto para guardar datos que tenemos representados en clases, en ficheros, sin complicarnos demasiado la vida. Es decir, a veces, necesitamos algo rápido para guardar en ficheros o para transmitir información por la red.

La clase Java, el objeto, debe implementar la interfaz Serializable, y así será fácilmente guardable como fichero de texto. Al hacer un objeto serializable, de forma automática se podrá convertir en una cadena de texto, con lo que podremos guardar este contenido fácilmente en un fichero, transmitirlo por la red, en una BD, etc.. ¡vamos a grano!

El código

Marco en negrita los códigos que hacen que un objeto se haga serializable. Aquí se almacenan dichos objetos en un array, así lo que se guarda es el array y de una tacada se guardan todos los objetos que haya.

De igual forma se recuperan del disco para comprobar qué tal se han guardado:

import java.util.ArrayList;
import java.io.ObjectOutputStream;
import java.io.ObjectInputStream;
import java.io.FileOutputStream;
import java.io.FileInputStream;
import java.io.Serializable;

public class Serializando {
    @SuppressWarnings({ "unchecked" })
    public static void main(String[] arg) {

        ArrayList <Objeto> arrayList1 = new ArrayList <Objeto>();
        ArrayList <Objeto> arrayList2;

        System.out.println("Datos que vamos a escribir en el fichero:");
        for(int i = 0; i < 10; i++) {
            Objeto nuevoObjeto = new Objeto("Cadena" + i);
            arrayList1.add(nuevoObjeto);
            System.out.println( "arrayList1[" + i + "] = " + arrayList1.get(i) );
        }

        try {
            System.out.print("Guardando ArrayList en el fichero objetos.dat.. ");

            ObjectOutputStream escribiendoFichero = new ObjectOutputStream( 
            new FileOutputStream("objetos.dat") );
            escribiendoFichero.writeObject(arrayList1);
            escribiendoFichero.close();

            System.out.println("ok!");
            System.out.print("Leyendo ArrayList del fichero objetos.dat.. ");

            ObjectInputStream leyendoFichero = new ObjectInputStream( 
            new FileInputStream("objetos.dat") );
            arrayList2 = ( ArrayList <Objeto> )leyendoFichero.readObject();
            leyendoFichero.close();

            System.out.println("ok!");
            System.out.println("Datos leídos del fichero:");

            for(int i = 0; i < arrayList2.size(); i++) {
                System.out.println( "arrayList2[" + i + "] = " + arrayList2.get(i) );
            }
        } catch (Exception e) {
            System.out.println( e.getMessage() );
        }

    }

}

class Objeto implements Serializable {
    private String _dato;

    public Objeto (String dato) {
        this._dato = dato;
    }

    public String toString() {
        return this._dato;
    }
}

Ejecutando

Ahora para ejecutarlo tenemos que ejecutar desde línea de comandos lo siguiente:

$ javac Serializando.java
$ java Serializando

Si todo ha ido bien tenemos que ver en pantalla lo siguiente:

Datos que vamos a escribir en el fichero:
arrayList1[0] = Cadena0
arrayList1[1] = Cadena1
arrayList1[2] = Cadena2
arrayList1[3] = Cadena3
arrayList1[4] = Cadena4
arrayList1[5] = Cadena5
arrayList1[6] = Cadena6
arrayList1[7] = Cadena7
arrayList1[8] = Cadena8
arrayList1[9] = Cadena9
Guardando ArrayList en el fichero objetos.dat.. ok!
Leyendo ArrayList del fichero objetos.dat.. ok!
Datos leídos del fichero:
arrayList2[0] = Cadena0
arrayList2[1] = Cadena1
arrayList2[2] = Cadena2
arrayList2[3] = Cadena3
arrayList2[4] = Cadena4
arrayList2[5] = Cadena5
arrayList2[6] = Cadena6
arrayList2[7] = Cadena7
arrayList2[8] = Cadena8
arrayList2[9] = Cadena9

Ya está no tiene más historia. Espero que sirva. ¡Un saludo!

18 respuestas a “Java: serializando objetos para guardar y recuperar en ficheros (editado)”

  1. Merelyn R. dice:

    Muy útil. Llevo varias horas tratando de encontrar la forma de guardar dinámicamente objetos en mi fichero y poder leerlos todos, y lo logré hasta ahora con ayuda de este código. Muchísimas gracias!

  2. Adriana dice:

    Hola, deseo realizar que un programa pueda un usuario baje un PDF individual y lo guarde en su PC, . Vos me puedes ayudar en eso??

    Mb tu propuesta por eso te escribo.

    Gracias.

    • Jnj dice:

      Hola Adriana.
      No acabo de entender bien la especificación de tu comentario. Pero gracias por dejar un comentario. Y he encontrado éste código fuente en Java que te podría ayudar:

      try (BufferedInputStream inputStream = new BufferedInputStream(new URL(«http://www.dominiodelaweb.com/nombre-fichero.pdf»).openStream());
      FileOutputStream fileOS = new FileOutputStream(«/Users/username/Documents/nombre-fichero.pdf»)) {
      byte data[] = new byte[1024];
      int byteContent;
      while ((byteContent = inputStream.read(data, 0, 1024)) != -1) {
      fileOS.write(data, 0, byteContent);
      }
      } catch (IOException e) {
      // handles IO exceptions
      }

      ..lo he sacado de https://stackabuse.com/how-to-download-a-file-from-a-url-in-java/. Espero que sirva.
      Un saludo!

  3. Jose dice:

    Y como se haría para cargar ese mismo archivo de datos en el arraylist1

    • Jnj dice:

      En la parte donde se carga en arrayList2 lo tienes. Sería lo mismo pero poniendo arrayList1.
      Un saludo José.

      • Jose dice:

        Que va tengo un código como este y no me deja.

        El arraylist que guardo y cargo es este.

        ArrayList Usuarios = new ArrayList();

        case 4:
        System.out.print(«Guardando datos en el fichero datos.dat.. «);

        ObjectOutputStream escribiendoFichero = new ObjectOutputStream(new FileOutputStream(«datos.dat»));
        escribiendoFichero.writeObject(Usuarios);
        escribiendoFichero.close();

        System.out.println(«Datos Guardados con exito!»);

        break;
        case 5:
        System.out.print(«Leyendo ArrayList del fichero datos.dat.. «);

        ObjectInputStream leyendoFichero = new ObjectInputStream(new FileInputStream(«datos.dat»));
        Usuarios = (ArrayList) leyendoFichero.readObject(); //En esta línea me da error el codigo
        leyendoFichero.close();

        System.out.println(«ok!»);
        System.out.println(«Datos leídos del fichero:»);
        break;

        • Jnj dice:

          Creo que falla porque no has declarado el tipo de objeto que guardas en la lista, ni luego al cargarlo desde fichero el casting de lo que lees:
          ..
          ArrayList <Usuario> usuarios = new ArrayList <Usuario>();
          ..
          escribiendoFichero.writeObject(usuarios);
          ..
          usuarios = ( ArrayList <Usuario> ) leyendoFichero.readObject();
          ..
          Un saludo José.

  4. Pipe dice:

    Como haría para cargar un archivo.dat ya serializado en una Jtable y también guardar los elementos que ya se agregaron a la Jtable en un archivo.dat ya serializado??

  5. Lauro Jimenez dice:

    Yo obtengo un error que no me deja correr el programa, es el siguiente…..

    local class incompatible: stream classdesc serialVersionUID = 6529685098267757690, local class serialVersionUID = 8603723807187381908

  6. Codexna dice:

    Pero el casting da un Warning de unsafety cast y para ello hay que hacer un cast sin declarar el tipo de dato arraylist2 = (ArrayList())
    LeyendoFichero.readObject() ;
    Y luego recorres el arraylist2 y añades los objetos del arraylist2 al arraylist1 con un casting al tipo de Objeto, así
    arraylist1.add((Objeto) arraylist2.get(i);

  7. Fatima dice:

    Tengo este código y aunque ya busque la manera de arreglarlo no me sale, me podría ayudar

    1) PersonaBean

    package mx.startonline.beans;

    import java.io.Serializable;

    public class PersonaBean implements Serializable {
    private String Nombre;
    private String Apellido;
    private String edoCivil;
    private int edad;

    public PersonaBean() {

    }

    public String getNombre() {
    return Nombre;
    }

    public void setNombre(String nombre) {
    Nombre = nombre;
    }

    public String getApellido() {
    return Apellido;
    }

    public void setApellido(String apellido) {
    Apellido = apellido;
    }

    public String getEdoCivil() {
    return edoCivil;
    }

    public void setEdoCivil(String edoCivil) {
    this.edoCivil = edoCivil;
    }

    public int getEdad() {
    return edad;
    }

    public void setEdad(int edad) {
    this.edad = edad;
    }

    }

    2)RecibePersona

    package mx.startonline.beans;

    public class RecibePersona {

    public RecibePersona() {
    RegistroPersona registroPersona = new RegistroPersona();
    PersonaBean personaBean = registroPersona.creaPersona();
    System.out.println(«Nombre: » + personaBean.getNombre() );
    System.out.println(«Apellidos: » + personaBean.getApellido() );
    System.out.println(«Edo Civil: » + personaBean.getEdoCivil() );
    System.out.println(«Edad: » + personaBean.getEdad() );
    }

    public static void main(String[] args) {

    new RecibePersona();
    }

    }

    3) RegistroPersona

    package mx.startonline.beans;

    public class RegistroPersona {
    PersonaBean personaBean;
    protected PersonaBean creaPersona() {
    personaBean = new PersonaBean();
    personaBean.setNombre(«Leonardo»);
    personaBean.setApellido(«PalaciosMartinez»);
    personaBean.setEdoCivil(«Viudo»);
    personaBean.setEdad(19);
    return personaBean;
    }
    }

    • Jnj dice:

      Buenas tardes Fátima!
      No veo el problema, tu código lo estoy probando en mi ordenador y funciona perfectamente. Se ve por pantalla lo siguiente al lanzar el main:
      Nombre: Leonardo
      Apellidos: PalaciosMartinez
      Edo Civil: Viudo
      Edad: 19

      Saludos.

  8. Eduardo PG dice:

    Hola que tal. Sabes he estdo utilizando una clase, por ejemplo persona, y al guardar los registros los hago guardando bytes, o enteros o boolean, osea para recuperar un registro hago como 10 lecturas, pero conforme iba avanzando mi aplicacion la cantidad de registros aumenta y por ende la cantidad de lecturas tambien. Ahora cuando corro mi aplicacion y muestro los registros guaradados anterirormente, el ordenador se demora como 2 segundos en mostrarlos en mi JTable, (hablo de 20 registros por lo menos ). Entonces conforme haga mas registros, ala hora de leerlos va a demorar mas. Ahora que me recomiendas para guardar y leerlos? Seria de Serializar cada clase a guardar? Seria mas rapida o no cambia mucho? Entonces debo usar base de datos para una lectura mad rapida?

    • Jnj dice:

      Hola Eduardo.
      Pienso que estás en lo correcto. El guardado y recuperación desde ficheros, si es para un uso intensivo, o para cantidades muy grandes de información, mejor si lo haces usando una base de datos. El serializar objetos viene bien para ficheros de configuraciones, usos puntuales pero no intensos de esta información, también se usa para transmitir información entre procesos o entre ordenadores por red, etc.. Es decir, para un JTable con mucha información mejor usar una base de datos.
      Saludos.

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

 

© 2022 JnjSite.com - MIT license

Sitio hecho con WordPress, diseño y programación del tema por Jnj.