How to read a list of serialized objects saved in a java file?

Asked

Viewed 1,077 times

4

I wanted to work with serialization in java files and I read this tutorial about how to write the object in the file and this one on the how to read the file object

Then I created the following class that saves the Adreess object in the file "file.ser":

    import java.io.FileInputStream;
    import java.io.FileOutputStream;
    import java.io.ObjectInputStream;
    import java.io.ObjectOutputStream;
    import wl.revisao.write.Address;

    public class WriteObject {

        public void serializeAddressJDK7(Address address) {

            try (ObjectOutputStream oos
                    = new ObjectOutputStream(new FileOutputStream("arquivo.ser",true))) {

                oos.writeObject(address);
                System.out.println("Done");

            } catch (Exception ex) {
                ex.printStackTrace();
            }

        }

         public Address deserialzeAddressJDK7(String filename) {

            Address address = null;

            try (ObjectInputStream ois
                    = new ObjectInputStream(new FileInputStream(filename))) {

                address = (Address) ois.readObject();

            } catch (Exception ex) {
                ex.printStackTrace();
            }

            return address;

        }

//Method indicated by friend Isac with the answer below

public List<Address> recuperarTodos() {
        List<Address> addresses = new ArrayList<Address>(); //lista de Address

        try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream("arquivo.res"))) {

            while (true) {
                Address address = new Address();

                address = (Address) ois.readObject(); //le outro objeto e adicionar à lista
                addresses.add(address); //le outro objeto e adicionar à lista
            }

        } catch (EOFException ex) {

        } catch (Exception ex) {
            ex.printStackTrace();
        }
        return addresses;

    }

}

Here’s my main class:

public class Main {

    public static void main(String args[]) {

        WriteObject obj = new WriteObject();

        Address address = new Address();
        address.setStreet("Wall street");
        address.setCountry("United States Of America");

        Address address2 = new Address();
        address2.setStreet("Avenida Brasil");
        address2.setCountry("Brasil");

        obj.serializeAddressJDK7(address);
        obj.serializeAddressJDK7(address2);

//   obj.deserialzeAddressJDK7("arquivo.ser");
       System.out.println(obj.recuperarTodos());
    }
}

The other method deserialAddressJDK7 returns an Address object read from the file.

OK everything is perfect!! The problem is when I save more than one object in the file ".ser file" because the method was built to read only one object saved in the file;

How do I return a list of objects saved in that file?

Last, the infamous Address class:

public class Address implements Serializable {

    private static final long serialVersionUID = 1L;

    String street;
    String country;

    public Address() {
    }

    public void setStreet(String street) {
        this.street = street;
    }

    public void setCountry(String country) {
        this.country = country;
    }

    public String getStreet() {
        return this.street;
    }

    public String getCountry() {
        return this.country;
    }

    @Override
    public String toString() {
        return new StringBuffer(" Street : ")
                .append(this.street).append(" Country : ")
                .append(this.country).toString();
    }

}

ps: I’m using the append as true, because as we know I want to accumulate the objects in the file.ser , and if I omitted it, this would not be possible!
If there is another way to save the objects in the files without using the append , and it is possible to list these files, I would be happy to know. I used the Boolean append with true , because it was the only alternative I had... I didn’t know how to rewrite the file without deleting the previously existing objects!

  • @Thanks a guy I’ll take a look!

1 answer

3


To read a list of objects in the file you have to use a loop/loop in the reading part and go adding the read objects to a list:

List<Address> addresses = new ArrayList<Address>(); //lista de Address

try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream(filename))) {       

    while(true){
        addresses.add((Address) ois.readObject()); //le outro objeto e adicionar à lista
    }

} catch (EOFException ex){
    //fim da leitura aqui
} catch (Exception ex) {
    ex.printStackTrace();
}

Note that loop was marked as infinite and the end of the reading was captured with EOFException which may seem strange. In fact the null is a valid value to get from reading an object and so it is not possible to test the end against null but only capturing exceptions.

We may question Java’s decision to implement the end of the file through exceptions but that’s how it was implemented for ObjectInputStream and readObject.

I leave the note that writing with append to true you will not be able to deserialize multiple objects!

That said I show an example of how to use this logic without the append true, trying to make her look more like the one she had:

public class WriteObject {

    //guarda a stream de saída aqui considerando N escritas seguidas pois não tem 
    //append e apenas no fim uma unica leitura para os objetos todos
    private ObjectOutputStream oos; 

    public void serializeAddressJDK7(Address address) {

        try {
            if (oos == null){ //se é o primeiro objeto a guardar inicia a stream
                oos = new ObjectOutputStream(new FileOutputStream("arquivo.ser"));
            }

            oos.writeObject(address);
            System.out.println("Done");

        } catch (Exception ex) {
            ex.printStackTrace();
        }

    }

    public List<Address> recuperarTodos(String filename) {

        try {
            oos.close(); //tenta fechar a stream de saída
        } catch (IOException e) {
            e.printStackTrace();
        }

        List<Address> addresses = new ArrayList<Address>();

        try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream(filename))) {
            while (true) {
                addresses.add((Address) ois.readObject());
            }       
        } catch (EOFException ex) {
            // fim da leitura aqui
        } catch (Exception ex) {
            ex.printStackTrace();
        }

        return addresses;
    }

}

Testing now on main:

public static void main(String[] args) {
    ...
    obj.serializeAddressJDK7(address);
    obj.serializeAddressJDK7(address2);

    obj.recuperarTodos("arquivo.ser").stream().forEach(x-> System.out.println(x));

Exit:

inserir a descrição da imagem aqui

  • It can only return to the List when the file has only one object! Here is the error:java.io.Streamcorruptedexception: invalid type code: AC at java.io.Objectinputstream.readObject0(Objectinputstream.java:1381) at java.io.Objectinputstream.readObject(Objectinputstream.java:373) wl.revisao.write2.WriteObject.recuperarTodos(Writeobject.java:58) at wl.revisao.write2.Main.main(Main.java:28)

  • @Penapintada I assume the method recuperarTodos whatever the code I put here has. What is your signature ? And which path is being passed/used in this method ?

  • I’ll put it in the code above

  • @The problem has to do with the append true, which basically doesn’t work with writeObject and ReadObject. There is even a related question on Soen with this problem of append. And I’ve been able to test it here without the append and it works but you have to give another logic to the program/class WriteObject. So I’m more tempted to remove my answer than change the logic of what’s in the question

  • That’s right I’m using the append, thanks for the support.

  • @Penapintada Com append does not work to deserialize multiple objects, you can test even in a direct way running obj.deserialzeAddressJDK7("arquivo.ser"); as it was in your main 2 times in a row, deleting even all the code I made, which always appears the first. And if you test within the method deserialzeAddressJDK7 two readings in a row with address = (Address) ois.readObject(); has the same mistake.

  • Thank you guys! Great answer. Now another question is born that will be for the next! I hope to count on Voce...

  • @Nothing. I’ll be watchful! All the best for you.

Show 3 more comments

Browser other questions tagged

You are not signed in. Login or sign up in order to post.