Foro de elhacker.net

Programación => Java => Mensaje iniciado por: Aikanáro Anário en 6 Febrero 2012, 18:19 pm



Título: Obtener información de varios objetos al leer archivo serializado
Publicado por: Aikanáro Anário en 6 Febrero 2012, 18:19 pm
Me guié de un vídeo para aprender el tema de Serialización en Java. En el que tenemos una clase Contacto que implementa la interfaz Serializable con los atributos Nombre y Apellido y sus respectivos getters y setters.

Clase Contacto:
Código
  1. // El objeto que voy a serializar (en este caso Contacto) debe implementar la interfaz Serializable.
  2. import java.io.*;
  3.  
  4. public class Contacto implements Serializable{
  5.  
  6. private String nombre;
  7. private String apellido;
  8.  
  9. public Contacto(String nombre, String apellido){
  10. this.nombre = nombre;
  11. this.apellido = apellido;
  12. }
  13.  
  14. public String getNombre(){
  15. return this.nombre;
  16. }
  17.  
  18. public String getApellido(){
  19. return this.apellido;
  20. }
  21.  
  22. public void setNombre(String n){
  23. this.nombre = n;
  24. }
  25.  
  26. public void setApellido(String a){
  27. this.apellido = a;
  28. }
  29.  
  30. public String toString(){
  31. return this.getApellido() +" "+ this.getNombre();
  32. }
  33. }

Tengo la clase Serializador que tiene los métodos para escribir un archivo y leer un archivo.

Clase Serializador:

Código
  1. import java.io.*;
  2.  
  3. public class Serializador{
  4.  
  5. // Escribe un objecto en un archivo
  6. private ObjectOutputStream escritorArchivo;
  7.  
  8. // Lee un objecto que este guardado en un archivo
  9. private ObjectInputStream lectorArchivo;
  10.  
  11.  
  12. // Al metodo le pasamos el objeto que queremos serializar y lo guardará en el archivo que se le especifique al FileOutputStream (en este caso "objeto.mio")
  13. public void escribirArchivo(Object objeto){
  14. try{
  15. escritorArchivo = new ObjectOutputStream(new FileOutputStream("objeto.mio"));
  16. escritorArchivo.writeObject(objeto);
  17. } catch(FileNotFoundException fnfex){
  18. fnfex.printStackTrace();
  19. } catch(IOException ioex){
  20. ioex.printStackTrace();
  21. }
  22. }
  23.  
  24. public Object leerArchivo(String rutaArchivo){
  25. Object lectura = null;
  26. try{
  27. lectorArchivo = new ObjectInputStream(new FileInputStream(rutaArchivo));
  28. lectura = lectorArchivo.readObject();
  29. } catch(FileNotFoundException fnfex){
  30. fnfex.printStackTrace();
  31. } catch(IOException ioex){
  32. ioex.printStackTrace();
  33. } catch(ClassNotFoundException cnfex){
  34. cnfex.printStackTrace();
  35. }
  36. return lectura;
  37. }
  38.  
  39. }

Y la clase Main para serializar un objeto de tipo Contacto y después leerlo

Clase Main:
Código
  1. public class Main{
  2. public static void main(String[] args){
  3. Serializador ser = new Serializador();
  4.  
  5. Contacto yo = new Contacto("Gustavo","Diaz");
  6. Contacto prima = new Contacto("Madeline","Guzman");
  7.  
  8. ser.escribirArchivo(yo);
  9. ser.escribirArchivo(prima);
  10.  
  11. Contacto contacto = (Contacto) ser.leerArchivo("objeto.mio");
  12. System.out.println(contacto.getNombre());
  13. System.out.println(contacto.getApellido());
  14.  
  15. }
  16. }

Mi pregunta es ¿cómo puedo leer del archivo la información (en este caso nombre y apellido) de ambos contactos?
Así como está ahora, solo me imprime los datos del último objecto que se serializo, que se guardó en el archivo, que en este caso es el "Contacto prima". Yo quiero poder imprimir ambos nombres y apellidos o elegir cuando quiero imprimir lo del "Contacto yo" o los del "Contacto prima"


Título: Re: Obtener información de varios objetos al leer archivo serializado
Publicado por: @rkimedes en 9 Febrero 2012, 16:34 pm
Código:
public void escribirArchivo(Object objeto){
try{
if(escritorArchivo == null)
escritorArchivo = new ObjectOutputStream(new FileOutputStream("objeto.mio"));
escritorArchivo.writeObject(objeto);
} catch(FileNotFoundException fnfex){
fnfex.printStackTrace();
} catch(IOException ioex){
ioex.printStackTrace();
}
}

public Object leerArchivo(String rutaArchivo) {
Contacto contacto = null;
try{
if(lectorArchivo == null)
lectorArchivo = new ObjectInputStream(new FileInputStream(rutaArchivo));
while(true){
contacto = (Contacto) lectorArchivo.readObject();
System.out.println(contacto.getNombre() + " " + contacto.getApellido() );
}
}catch(EOFException ex)
{
System.out.println("\nFinal de archivo");
}catch (ClassNotFoundException e) {
e.printStackTrace();
}catch (IOException e) {
e.printStackTrace();
}
return contacto;
}



Código:
import java.io.IOException;

public class Main{
public static void main(String[] args)  {
Serializador ser = new Serializador();
Contacto yo = new Contacto("Gustavo","Diaz");
Contacto prima = new Contacto("Madeline","Guzman");
Contacto yotb = new Contacto("Juan","Villanueva");

ser.escribirArchivo(yo);
ser.escribirArchivo(prima);
ser.escribirArchivo(yotb);
ser.escribirArchivo(new Contacto("Jhonny","Walker"));

ser.leerArchivo("objeto.mio");

}
}


Título: Re: Obtener información de varios objetos al leer archivo serializado
Publicado por: Aikanáro Anário en 10 Febrero 2012, 00:57 am
Gracias! Entiendo lo que has hecho. Aunque no lo he probado, sé que eso me traerá toda la información que hay guardada en el archivo serializado, en este caso, todos los Contactos que haya serializado anteriormente. Y eso en parte contesta mi pregunta, pero ¿Qué pasa si después de serializar o guardar 3 contactos en el archivo, digamos Juan, Pedro y Fulano, quisiera ver solamente los datos de Juan?

Bueno, acabo de probar y aunque parecía que iba a funcionar sigue pasando lo mismo: solo devuelve el último nombre que se guardó/serializó.

Código
  1. public void leerArchivo(String rutaArchivo){
  2. Contacto contacto = null;
  3. try{
  4. if(lectorArchivo == null){
  5. lectorArchivo = new ObjectInputStream(new FileInputStream(rutaArchivo));
  6. }
  7. while(true){
  8. contacto = (Contacto) lectorArchivo.readObject();
  9. System.out.println(contacto.getNombre() +" "+ contacto.getApellido());
  10. }
  11. } catch(EOFException eofex){
  12. System.out.println("Fin de linea \n");
  13. } catch(IOException ioex){
  14. ioex.printStackTrace();
  15. } catch(ClassNotFoundException cnfex){
  16. cnfex.printStackTrace();
  17. }
  18. }

Código
  1. public class Main{
  2. public static void main(String[] args){
  3. Serializador ser = new Serializador();
  4.  
  5. Contacto yo = new Contacto("Gustavo","Diaz");
  6. Contacto prima = new Contacto("Madeline","Guzman");
  7.  
  8. ser.escribirArchivo(yo);
  9. ser.escribirArchivo(prima);
  10.  
  11. ser.leerArchivo("objeto.mio");
  12.  
  13. }
  14. }


Título: Re: Obtener información de varios objetos al leer archivo serializado
Publicado por: @rkimedes en 10 Febrero 2012, 13:13 pm
Hola el problema por el cual solo mostraba el ultimo objeto, era porque se abria el archivo en cada escritura y copiaba encima el nuevo objeto, para poder acceder a un objeto X por el nombre, cree un hashmap en el que en cada escritura, a cada nombre se le asocia un número empezando por el 0,  para realizar la búsqueda por nombre sobrecargue tu método  leerArchivo.
La función  hashmap.get(nombre).intValue() devuelve el entero que se asocio al crear el hashmap y como la lectura es secuencial desde que se abre el archivo lee la posición 0 objeto 0, itero las veces que sea necesarias para encontrar el objeto a mostrar.
Prueba este código tal cual está solo hice cambios en la clase Serializador, para acceder a algún dato en particular seria ser.leerArchivo("objeto.mio","Juan"); si el nombre no existe en el hasmap te lo indicara con un System.out.print. ::)


Código
  1.  
  2. import java.io.*;
  3. import java.util.HashMap;
  4. import java.util.Map;
  5.  
  6. public class Serializador{
  7. // Escribe un objecto en un archivo
  8. private ObjectOutputStream escritorArchivo = null;
  9.  
  10. // Lee un objecto que este guardado en un archivo
  11. private ObjectInputStream lectorArchivo = null;
  12.  
  13. private Map<String, Integer> hashmap = new HashMap<String, Integer>();
  14.  
  15. private static int con = 0;
  16.  
  17. // Al metodo le pasamos el objeto que queremos serializar y lo guardará en el archivo que se le especifique al FileOutputStream (en este caso "objeto.mio")
  18. public void escribirArchivo(Object objeto){
  19. try{
  20. if(escritorArchivo == null)
  21. escritorArchivo = new ObjectOutputStream(new FileOutputStream("objeto.mio"));
  22. escritorArchivo.writeObject(objeto);
  23. hashmap.put(((Contacto)objeto).getNombre(), con++);
  24. } catch(FileNotFoundException fnfex){
  25. fnfex.printStackTrace();
  26. } catch(IOException ioex){
  27. ioex.printStackTrace();
  28. }
  29. }
  30.  
  31. public Object leerArchivo(String rutaArchivo) {
  32. Contacto contacto = null;
  33. try{
  34. if(lectorArchivo == null)
  35. lectorArchivo = new ObjectInputStream(new FileInputStream(rutaArchivo));
  36. while(true){
  37. contacto = (Contacto) lectorArchivo.readObject();
  38. System.out.println(contacto.getNombre() + " " + contacto.getApellido() );
  39. }
  40. }catch(EOFException ex)
  41. {
  42. System.out.println("\nFinal de archivo");
  43. e.printStackTrace();
  44. }catch (IOException e) {
  45. e.printStackTrace();
  46. }
  47. return contacto;
  48. }
  49.  
  50. public Object leerArchivo(String rutaArchivo, String nombre) {
  51. Contacto contacto = null;
  52. int contador = 0;
  53. try{
  54. lectorArchivo = new ObjectInputStream(new FileInputStream(rutaArchivo));
  55. if(hashmap.get(nombre)!= null){
  56. int numero = hashmap.get(nombre).intValue();
  57. while(contador <= numero){
  58. contacto = (Contacto) lectorArchivo.readObject();
  59. contador++;
  60. }
  61. System.out.println(contacto.getNombre() + " " + contacto.getApellido() );
  62. }
  63. else{
  64. System.out.println("El nombre no se encuentra en el archivo");
  65. }
  66. lectorArchivo.close();
  67. }catch(EOFException ex)
  68. {
  69. System.out.println("\nFinal de archivo");
  70. e.printStackTrace();
  71. }catch (IOException e) {
  72. e.printStackTrace();
  73. }
  74.  
  75. return contacto;
  76. }
  77. }
  78.  
  79.  


Título: Re: Obtener información de varios objetos al leer archivo serializado
Publicado por: Aikanáro Anário en 11 Febrero 2012, 03:56 am
Gracias, mano!

Tengo que estudiar la clase Hashmap para entender mejor.