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

4

I was looking to work with serialization in java files and read this tutorial on 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;

        }
  

// Friend Isac's method 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 is 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 deserialzeAddressJDK7 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 "file.ser" because the method was built to read only one object saved in the file;

  

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

Finally the infamous class Address:

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 append as true, because as we know I want to accumulate the objects in the .ser file, and if I omitted it, that would not be possible! If there is another way to save the objects to the files without using append, and you can list those files, I'd be happy to see them. I used Boolean append commo true, because it was the only alternative I had ... I did not know how to rewrite in the file without deleting previously existing objects!

    
asked by anonymous 17.10.2017 / 00:53

1 answer

3

To read a list of objects in the file you must use a loop / loop in the reading part and add 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 infinity and the end of the reading was caught with EOFException which may seem strange. In fact, null is a valid value to get reading an object and so it is not possible to test the end by comparing with null but only by catching exceptions.

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

This shows an example of how to use this logic without append true , trying to make it look more like the one it 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));

Output:

    
17.10.2017 / 01:43