Persistência de Objetos Java em Arquivos

Persistindo Objetos Java em Arquivos

Neste artigo veremos como fazer para salvar um objeto Java para um arquivo, e como recuperá-lo depois.  O arquivo será armazenado em formato binário, por meio da funcionalidade de Serialização do Java.

Outras maneiras de armazenar um objeto seria por meio de outros formatos, como XML ou JSON, que podem facilitar a interoperabilidade entre plataformas; ou em um arquivo puramente texto , para facilitar a manipulação por usuários, entre outros.

Em nosso exemplo é suficiente gravar e recuperar o arquivo diretamente como um binário.

1. Gravando Objetos Java em arquivo


import java.io.FileOutputStream;

import java.io.ObjectOutputStream;

 

public class SalvarObjeto {

 

    public static void salvar(Object objeto, String caminho) {

 

           try {

             FileOutputStream saveFile = new FileOutputStream(caminho);

             ObjectOutputStream stream = new ObjectOutputStream(saveFile);

 

              // salva o objeto

             stream.writeObject(objeto);

 

             stream.close();

           } catch (Exception exc) {

             exc.printStackTrace();

           }

    }

}

 

No código anterior, criamos a classe SalvarObjeto, que possui apenas um método que recebe um objeto a ser salvo e o caminho. O tratamento de exceção foi simplificado apenas para mostrar o código que interessa:

  1. O arquivo é aberto em uma FileOutputStream . Caso o arquivo não exista, ele é criado.
  2. É criado um ObjectOutputStream a partir da stream anterior.
  3. Ao escrever no ObjectOutputStream, os dados são enviados por meio da FileOutputStream para o arquivo físico.
  4. Por fim, a stream é fechada.

 

Você pode experimentar salvar objetos simples, como Strings, Arrays ou Listas de objetos. Mas vamos criar uma entidade um pouco mais robusta, para exercitar o exemplo:

 

public class Cidade implements Serializable {

 

       private static final long serialVersionUID = -7932047122858971692L;

 

       static class Ponto implements Serializable {

            

             private static final long serialVersionUID = 2651887979907L;

 

             double x, y;

             public Ponto(double x, double y) {

                    this.x = x;

                    this.y = y;

             }

       }

      

       String nome;

       Ponto coordenadas;

       int populacao;

       boolean cidadePortuaria;

       List<String> palavras_chave;

       Bairro[] bairros;

      

       public Cidade(String nome, double geox, double geoy, int populacao, boolean portuaria, List<String> palavras, Bairro[] bairros) {

             this.nome = nome;

             this.coordenadas = new Ponto(geox, geoy);

             this.populacao = populacao;

             this.cidadePortuaria = portuaria;

             this.palavras_chave = palavras;

             this.bairros = bairros;

       }

}

 

Esse exemplo “Cidade” possui atributos diversos: tipos primitivos, objetos, lista de objetos, e um array do objeto “Bairro”, que é dessa forma:

 

import java.io.Serializable;

import java.util.EnumSet;

 

public class Bairro implements Serializable {

 

       private static final long serialVersionUID = 5110549514946052395L;

 

       String nome;

       boolean temPraia;

 

       public static enum Qualidade {COMERCIAL, PRAIA, TURISMO, RESIDENCIAL};

       EnumSet<Qualidade> qualidades = EnumSet.noneOf(Qualidade.class);

      

       public Bairro(String nome, boolean praia, EnumSet<Qualidade> qualidades) {

             this.nome = nome;

             this.temPraia = praia;

             this.qualidades = qualidades;

       }

      

}

É muito importante declarar em todas as classes que serão serializadas a interface Serializable. Sem isso ocorrerá uma exceção ao tentar escrever o objeto.

Para testar a escrita do arquivo, vamos criar essa classe para executar a gravação do arquivo a partir do método main:

import java.util.Arrays;

import java.util.EnumSet;

 

public class SalvarObjetoTest {

 

       public static void main(String args[]) {

            

             // Cria o objeto

             Cidade cidade = new Cidade("Rio de Janeiro", -22.90833, -43.19639, 6323037, true,

                           Arrays.asList("Praias", "Corcovado", "Pão de Açúcar", "Cidade Maravilhosa"),

                           new Bairro[]{

                                  new Bairro("Tijuca", false, EnumSet.of(Bairro.Qualidade.RESIDENCIAL)),

                                  new Bairro("Copacabana", true, EnumSet.of(Bairro.Qualidade.RESIDENCIAL, Bairro.Qualidade.COMERCIAL, Bairro.Qualidade.TURISMO)),

                                  new Bairro("Centro", false, EnumSet.of(Bairro.Qualidade.COMERCIAL)),

                                  new Bairro("Ipanema", true, EnumSet.of(Bairro.Qualidade.TURISMO, Bairro.Qualidade.RESIDENCIAL)),

                                  new Bairro("Leblon", true, EnumSet.of(Bairro.Qualidade.TURISMO, Bairro.Qualidade.RESIDENCIAL))

                           }

                    );

                          

             // Salva o objeto

             SalvarObjeto.salvar(cidade, "C:\\Treinamento\\Cidade.sav");

       }

}

 

Pronto, conseguimos criar uma instância do objeto Cidade, que possui um array de Bairros e outros atributos variados. Defina o caminho a ser gravado no parâmetro da chamada do método salvar (substitua o “C:\\Treinamento\Cidade.sav”). Note que o arquivo será criado após a execução do método main.

 

2. Restaurando Objetos Java a partir de um arquivo

Restaurar um arquivo é tão fácil quanto gravar:

 

       import java.io.FileInputStream;

       import java.io.ObjectInputStream;

 

       public class RestaurarObjeto {

 

             public static Object restaurar(String caminho) {

 

                    Object objeto = null;

                   

                    try {

                           FileInputStream restFile = new FileInputStream(caminho);

                           ObjectInputStream stream = new ObjectInputStream(restFile);

 

                           // recupera o objeto

                           objeto = stream.readObject();

 

                           stream.close();

                    } catch (Exception e) {

                           e.printStackTrace();

                    }

 

                    return objeto;

             }

       }

 

Neste código é feito o seguinte:

  1. É aberta uma FileInputStream, passando o caminho recebido por parâmetro;
  2. É criada uma ObjectInputStream a partir da stream anterior;
  3. O objeto é lido e atribuído para a variável “objeto”;
  4. A stream é fechada;
  5. O objeto é retornado.

Novamente, o tratamento de exceção foi simplificado, apenas a título de simplificar o exemplo.

A classe para testar esse método é ainda mais simples:

public class RestaurarObjetoTest {

 

       public static void main(String args[]) {

            

             // Restaura e Imprime os valores

             System.out.println((Cidade) RestaurarObjeto.restaurar("C:\\Treinamento\\Cidade.sav"));       

            

       }

      

}

Para imprimir o objeto Cidade de forma mais legível, inclua esse trecho de código na classe Cidade, fazendo a sobreposição do método toString():

 

       @Override

       public String toString() {

             StringBuilder strUtil = new StringBuilder();

             strUtil.append("Cidade:\n"this.nome);

             strUtil.append("\n\tCoordenadas: "this.coordenadas.x + "," +   this.coordenadas.y);

             strUtil.append("\n\tPopulação: "this.populacao);

             strUtil.append("\n\tCidade Portuária: " + ( this.cidadePortuaria ? "Sim" : "Não"));

             strUtil.append("\n\tPalavras-Chave: "this.palavras_chave);

 

             strUtil.append("\n\tBairros");

             for(Bairro bairro: this.bairros) {

                    strUtil.append("\n\t\tNome do Bairro: " + bairro.nome);

                    strUtil.append("\n\t\t\tTem praia?: " + (bairro.temPraia ? "Sim" : "Não"));

                    strUtil.append("\n\t\t\tCaracterísticas: " + bairro.qualidades);

             }

             return strUtil.toString();

       }

 

Pronto, ao executar o teste pela classe RestaurarObjetoTest, ele vai abrir o arquivo salvo previamente, e imprimir o seguinte:

 

Cidade:

Rio de Janeiro

       Coordenadas: -22.90833,-43.19639

       População: 6323037

       Cidade Portuária: Sim

       Palavras-Chave: [Praias, Corcovado, Pão de Açúcar, Cidade Maravilhosa]

       Bairros

             Nome do Bairro: Tijuca

                    Tem praia?: Não

                    Características: [RESIDENCIAL]

             Nome do Bairro: Copacabana

                    Tem praia?: Sim

                    Características: [COMERCIAL, TURISMO, RESIDENCIAL]

             Nome do Bairro: Centro

                    Tem praia?: Não

                    Características: [COMERCIAL]

             Nome do Bairro: Ipanema

                    Tem praia?: Sim

                    Características: [TURISMO, RESIDENCIAL]

             Nome do Bairro: Leblon

                    Tem praia?: Sim

                    Características: [TURISMO, RESIDENCIAL]

 

 

Comments