1. Este site usa cookies. Ao continuar a usar este site está a concordar com o nosso uso de cookies. Saber Mais.

Gravar List<object> Java em ficheiros

Discussão em 'Programação' iniciada por luismauricio, 9 de Junho de 2007. (Respostas: 39; Visualizações: 5849)

  1. luismauricio

    luismauricio Power Member

    Boas tardes estou com um pequeno problema e precisava que me ajudassem a resolver.
    Precisava de Gravar uma lista de objectos em linguagem Java para ficheiros e posteriormente ler os mesmos.
    Para gravar eu fiz isto:

    try {
    FileOutputStream fos = new FileOutputStream("FornecedoresList.txt");
    ObjectOutputStream oos = new ObjectOutputStream(fos);
    oos.writeObject(folist);
    oos.close();
    }
    catch (Exception e) { e.printStackTrace(); }

    mas não sei se é possível e não sei como resolver o problema da leitura dos dados depois.
     
  2. SoundSurfer

    SoundSurfer Power Member

    Experimenta serializar a lista para Xml, e guardas o ficheiro.
    Depois é só "desserializar" para voltar a ler para memória.
    Só sei fazer isso em C#, não sei como é em java.
     
  3. MadOnion

    MadOnion Folding Member

    Na assinatura da classe, deve estar "implements Serializable". À partida esse código funciona bem, depois da dita implementação da interface.
     
  4. JPgod

    JPgod Moderador
    Staff Member


    Exacto, isso tem que implementar o Serializable:

    Se for uma classe independente sem interface, nem herança.

    PHP:
    import java.io.Serializable

    (public) class 
    XPTO implements Serializable
    {                                                                   

        static final 
    long serialVersionUID 0L;
        ...
    }
    A variável estática é obrigatória, pode ser qualquer inteiro long, no caso deixei 0L.

    Se for uma interface e uma classe que a implementa

    PHP:
    import java.io.Serializable

    (public) Interface 
    iXPTO extends Serializable
    {                                                                   
       ...
    PHP:
    (public) Class cXPTO implements iXPTO
    {
        static final 
    long serialVersionUID 0L;
        ...
    Não é necessário a classe importar o java.io.Serializable, a interface faz isso, embora tenha que ter a varável static da praxe.
     
    Última edição: 10 de Junho de 2007
  5. luismauricio

    luismauricio Power Member

    Desculpem lá mas podem me explicar como se eu fosse mesmo mesmo burro ( lol ).
    Eu tenho uma lista de objectos do tipo cliente com alguns atributos e queria guardar essa lista num ficheiro para depois mais tarde poder aceder.
    Podem me por mesmo o código. obrigado
     
  6. mcog_blaster

    mcog_blaster Power Member

    Experimenta
    Código:
    ....class Cliente implements Serializable { ......
    e vê se consegues reconstruir a a lista a partir do ficheiro, e nao esquecer que muito provavelmente tens de fazer cast ao object Cliente que vais ler do ficheiro
    Código:
    cliente = (Cliente)ois.readObject()....
    ois: ObjectInputStream.
     
  7. Spiderman

    Spiderman I folded Myself

    Boas

    Depois de ter ido buscar a minha retro escavadora, vou fazer aqui um post. :P

    Preciso de fazer a mesma coisa, ou seja, ter uma lista de clientes, em que cada um tem vários atributos (Nome, Morada, telem, etc...)

    Como o tópico é de à 2 anos atrás, queria saber se há uma maneira mais recente para o fazer, ou se tem de ser assim.
     
  8. Baderous

    Baderous Banido

    Queres o quê mesmo, definir essa lista? Gravá-la em ficheiro?
     
  9. Spiderman

    Spiderman I folded Myself

    Tou a usar o NetBeans

    Defini uma class Cliente.java, que tem este código:

    PHP:
    public class Cliente {

        
    String nome;
        
    String tel;
        
    String mail;

        public 
    void Cliente(){

              
    nome "";
              
    tel "";
              
    mail "";
        }

         public 
    void Cliente(String nomeString telString mail){

              
    this.nome nome;
              
    this.tel tel;
              
    this.mail mail;
         }
    }
    Depois criei uma classe ListaClientes.java, que não tenho a certeza se está correcto, mas como não dá erros no compilador...:

    PHP:
    import java.util.*;

    public class 
    ListaClientes {

        List 
    lista = new LinkedList();    // Doubly-linked list

        
    Cliente nameArray[] = {new Cliente()};
        List<
    Clientenames Arrays.asList(nameArray);

    }
    Agora, era preciso poder guardar a lista no disco. Tou a usar as listas porque me parece ser a melhor maneira para adicionar clientes, alterar dados de um cliente, ler os dados de um cliente, etc...
     
  10. Baderous

    Baderous Banido

    A classe Cliente tem ali aqueles 2 métodos, que pelo aspecto deveriam ser os construtores, e aquilo não está bem feito. Os construtores não têm tipo de retorno. Para além disso as variáveis de instância devem ser sempre private. Isso deveria estar assim:

    Código:
    import java.util.*;
    import java.io.*;
    
    public class Cliente implements Serializable {
    
        private String nome;
        private String tel;
        private String mail;
    
        public Cliente() { this("","",""); }
        
        public Cliente(String nome, String tel, String mail) {
            this.nome=nome;
            this.tel=tel;
            this.mail=mail;
        }
        
        public Cliente(Cliente c) {
            this.nome=c.getNome();
            this.tel=c.getTel();
            this.mail=c.getMail();
        }
        
        public String getNome() { return this.nome; }
        public String getTel() { return this.tel; }
        public String getMail() { return this.mail; }
        
        public String toString() {
            StringBuilder s = new StringBuilder();
            s.append("-- Cliente --\n");
            s.append("Nome: ");
            s.append(this.nome);
            s.append("\nTelefone: ");
            s.append(this.tel);
            s.append("\nMail: ");
            s.append(this.mail);
            s.append("\n");
            return s.toString();
        }
    
        public Cliente clone() { return new Cliente(this); }
    }
    Acrescentei uns métodos que são úteis mais à frente. Nota a implementação da interface Serializable de modo a permitir que as instâncias de Cliente possam ser escritas para ficheiro.

    Na classe da lista deves ter isto:

    Código:
    import java.util.*;
    import java.io.*;
    
    public class ListaClientes implements Serializable {
        private List<Cliente> lista;
    
        public ListaClientes() { this.lista = new ArrayList<Cliente>(); }
    
        public ListaClientes(Collection<? extends Cliente> col) {
            this();
            for (Cliente c : col)
                this.lista.add(c.clone());
        }
    
        public void addCliente(Cliente c) { this.lista.add(c.clone()); }
        
        public String toString() {
            StringBuilder s = new StringBuilder();
            s.append("-- Lista de Clientes --\n");
            for (Cliente c : this.lista)
                s.append(c.toString());
            return s.toString();
        }
        
        public void gravaObjStream(String fich) {
            ObjectOutputStream oout = null;
            try {
                oout = new ObjectOutputStream(new FileOutputStream(fich));
                oout.writeObject(this);
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                try {
                    if (oout!=null) {
                        oout.flush();
                        oout.close();
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    Aqui tens o método que te grava uma lista de cliente num ficheiro de objectos (e não num ficheiro de texto, para esse usas um tipo de stream diferente).

    Aqui tens a classe de teste:

    Código:
    import java.util.*;
    import java.io.*;
    
    public class Main {
        public static void main(String[] args) {
            ListaClientes l = new ListaClientes();
            l.addCliente(new Cliente("joao","2342556424","[email protected]"));
            l.addCliente(new Cliente("ze","245675675674564","[email protected]"));
            l.gravaObjStream("file.obj");
            ListaClientes nova = new ListaClientes();
            ObjectInputStream ooin = null;
            try {
                ooin = new ObjectInputStream(new FileInputStream("file.obj"));
                nova = (ListaClientes)ooin.readObject();
            } catch (IOException e) { e.printStackTrace(); }
            catch (ClassNotFoundException e) { e.printStackTrace(); }
            finally {
                try {
                    if (ooin!=null)
                        ooin.close();
                    } catch (IOException e) { e.printStackTrace(); }
            }
            System.out.println(nova);
       }
    }
        
            
    Como podes ver, carregaste com sucesso a lista previamente guardada em ficheiro.

    Quanto à estrutura de dados que usaste ser lista ou assim, isso depende muito do teu objectivo, se por acaso pretendesses não ter repetidos, um Set já seria melhor, etc.
     
  11. Spiderman

    Spiderman I folded Myself

    MUITO Obrigado!! Está impecável, vou agora adaptar isto ao meu código. :p

    Quanto ao facto de haver clientes iguais, eles vão ter nº cliente, portanto nunca haverá iguais. Como é que eu posso fazer para eles serem criados de forma crescente? Isto dará:

    Só outra coisa.

    Tentei utilizar na interface gráfica uma Jlist, que era para listar os clientes e depois de seleccionar um deles, carregar num botão "abrir" que mostrava os dados todos do cliente, mas não consegui por aquilo a adicionar linhas novas na jlist. Sei que em VB, e mesmo em java utilizando a AWT list é realmente fácil da fazer. Mas as Jlist são diferentes...

    Deu-me a entender que aquilo tem de receber um vector na construção da jlist...

    Cumps ;)
     
  12. Baderous

    Baderous Banido

    Para o 1º problema, a melhor solução é criar uma variável de classe que guarde o nº de instâncias de Cliente actualmente criadas e que seja incrementada sempre que é criada uma delas:

    Código:
    import java.util.*;
    import java.io.*;
    
    public class Cliente implements Serializable {
    
        public static int numClientes = 0;
        
        public static int getNumClientes() { return numClientes; }
        
        public static void incNumClientes() { numClientes++; }
    
        private String nome;
        private String tel;
        private String mail;
    
        public Cliente() { this("","",""); }
        
        public Cliente(String nome, String tel, String mail) {
            this.nome=nome;
            this.tel=tel;
            this.mail=mail;
            this.incNumClientes();
        }
    
    ...
    Depois para testar:

    Código:
    System.out.println(Cliente.getNumClientes());
    Para o 2º problema vê por aqui: http://java.sun.com/docs/books/tutorial/uiswing/components/list.html
     
  13. Spiderman

    Spiderman I folded Myself

    Mas eu no 1º caso não quero saber o numero de clientes totais. Eu quero é que cada cliente tenha um nº:

    PS: Consegui pôr a dar, mas reparei que utilizando o Clone() ele me incrementa 2 números. Acho que é por ele criar 2 Clientes, e leva-me a pensar que assim se eu precisar de criar um cliente para comparação, por exemplo, ele me vai aumentar o nº de clientes sem eu querer.
     
    Última edição: 27 de Novembro de 2009
  14. Baderous

    Baderous Banido

    Sim, mas tu disseste que os queres criar de forma ascendente, daí que precises, a cada momento, de saber quantos já existem para atribuíres um nº que esteja de acordo. Por exemplo, se souberes que já existem 6 clientes, então o próximo a criar terá o nº 7.

    Esse pormenor realmente advém do clone() uma vez que este método invoca o construtor, que por sua vez incrementa o nº de clientes.
    Se tiveres a certeza de que não vais alterar as instâncias de Cliente que adicionas à lista (isto é, se não crias a instância à parte, adicionas à lista e depois fazes alguma operação com a instância sem ser a que colocaste na lista), então podes tirar o clone. Tirando o clone, o que fazes é uma shallow copy (e não uma deep copy como estás a fazer agora), ou seja, o que colocas na lista é apenas a referência para a instância criada, pelo que qualquer alteração que faças na instância fora da lista, vai surtir efeito na lista (daí aquele parêntesis que fiz). Se optares por não retirar o clone, o que podes fazer é no próprio clone invocar um método static que definirás que te faz o decremento do nº de clientes (à semelhança do incNumClientes()).
     
    Última edição: 27 de Novembro de 2009
  15. Spiderman

    Spiderman I folded Myself

    Não está a funcionar. O problema do clone consegui resolver fazendo uma função com numClientes--.

    Mas o problema é que ele não guarda no ficheiro o numero de clientes. Fazendo a execução seguida, por exemplo, criar a lista->adicionar clientes->guardar->abrir->adicionar clientes, funciona.
    Mas depois de fechar o programa ele perde a variavel, e começa do zero.

    Alguma ideia?
     
    Última edição: 27 de Novembro de 2009
  16. 64kB

    64kB Banido

    Obrigado baderus, por acaso, também me ajudou, já agora.

    Se eu tiver um set dentro da minha classe "serializavel", um Set de objectos de classe, ele também salva esse set? Os objectos de esse set têm tb de ser serializaveis, certo?

    Já agora, isso está-me a gravar num formato meio esquisto, quando o abro, não dá para gravar num formato XML?
     
  17. Baderous

    Baderous Banido

    É verdade, as variáveis static não são serializáveis. Mas repara, se o problema é esse, ao leres a lista do ficheiro, calculas o seu tamanho e atribuis esse valor à variável de classe numClientes. Fazes algo tipo:

    Código:
    // ler a lista do ficheiro
    Cliente.setNumClientes(nova.tamanho());
    Onde o setNumClientes seria um método estático da classe Cliente que alterava o valor de numClientes.

    Sim, o set é guardado, tal como aqui é guardada a lista.
    Sim, os objectos têm também eles de ser serializáveis.
    Para gravares num formato XML podes usar uma API própria, recomendo a nova adição ao Mustang: JAXB (Java API for XML Binding). Página 29
     
  18. Spiderman

    Spiderman I folded Myself

    Está como a aço!

    Isto é para um trabalho, em que o sistema é client-server. Já pus uma janela com uma formulário em que adiciona os dados do cliente através deste sistema no servidor.

    Agora para actualizar a lista na Jlist, eu estava a pensar invocar um método na classe lista. Por exemplo este metodo:

    PHP:
        public String[] ListaClien (){
        
    String [] str = {""};
        for(
    int i=0;i<lista.size();i++)
            
    str[i] = lista.get(i).getNum()+" - "+lista.get(i).getNome();
        return 
    str;
        }
    Assim o programa criava a jlist a partir deste vector. Que te parece Baderous?
    E mais uma vez, muito obrigado pela ajuda ;)
     
  19. Baderous

    Baderous Banido

    Se te dá mais jeito, não vejo porque não. Mete só o nome do método a começar por minúscula para estar de acordo com as regras de escrita de código Java.
     
  20. Spiderman

    Spiderman I folded Myself

    Uma duvida

    Quero iniciar a jlist, e fiz isto na classe criada pelo netbeans na jframe:

    PHP:
    public GestaoClientes() {
        
    initComponents();
        
    String temp[]=Cliente_LN.act_listaClientes.actualiza_lista(numero_funcionario);
        }
    A função actualiza_lista é esta:

    PHP:
    public class act_listaClientes {

        
    Cliente_Com.SocketClient socket23;

    public 
    String[] actualiza_lista(int num_funcionario){

       try{
       
    String pedido "003#"+num_corretor;
       
    String outraresposta socket23.Socke(pedido); //Linha socket

       
    outraresposta Cliente_Com.Protocolo_Cliente.processarResposta(outraresposta);
       return 
    outraresposta.split("#");

       }catch (
    Exception e){}

       return 
    null;
    }
    }
    O problema, que já não é 1ª vez que ma aparece, é que no "GestaoClientes()" não consigo aceder à outra função. Pus a "actualiza_lista(int num_corretor)" como "static", mas depois da-me erro na "Linha socket", diz que a variável é non-static e não pode ser acedida em contexto static.
    Reparei que metento static atrás da variável "Cliente_Com.SocketClient socket23" resolve, mas será que é correto fazer isto?
     

Partilhar esta Página