Obtener información de varios objetos al leer archivo serializado

Iniciado por Aikanáro Anário, 6 Febrero 2012, 18:19 PM

0 Miembros y 1 Visitante están viendo este tema.

Aikanáro Anário

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 (java) [Seleccionar]
// El objeto que voy a serializar (en este caso Contacto) debe implementar la interfaz Serializable.
import java.io.*;

public class Contacto implements Serializable{

private String nombre;
private String apellido;

public Contacto(String nombre, String apellido){
this.nombre = nombre;
this.apellido = apellido;
}

public String getNombre(){
return this.nombre;
}

public String getApellido(){
return this.apellido;
}

public void setNombre(String n){
this.nombre = n;
}

public void setApellido(String a){
this.apellido = a;
}

public String toString(){
return this.getApellido() +" "+ this.getNombre();
}
}


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

Clase Serializador:

Código (java) [Seleccionar]
import java.io.*;

public class Serializador{

// Escribe un objecto en un archivo
private ObjectOutputStream escritorArchivo;

// Lee un objecto que este guardado en un archivo
private ObjectInputStream lectorArchivo;


// 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")
public void escribirArchivo(Object objeto){
try{
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){
Object lectura = null;
try{
lectorArchivo = new ObjectInputStream(new FileInputStream(rutaArchivo));
lectura = lectorArchivo.readObject();
} catch(FileNotFoundException fnfex){
fnfex.printStackTrace();
} catch(IOException ioex){
ioex.printStackTrace();
} catch(ClassNotFoundException cnfex){
cnfex.printStackTrace();
}
return lectura;
}

}


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

Clase Main:
Código (java) [Seleccionar]
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");

ser.escribirArchivo(yo);
ser.escribirArchivo(prima);

Contacto contacto = (Contacto) ser.leerArchivo("objeto.mio");
System.out.println(contacto.getNombre());
System.out.println(contacto.getApellido());

}
}


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"
Lo que faltaba en internet: http://binar10s.blogspot.com/

@rkimedes


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;
}





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");

}
}

Aikanáro Anário

#2
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 (java) [Seleccionar]
public void 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 eofex){
System.out.println("Fin de linea \n");
} catch(IOException ioex){
ioex.printStackTrace();
} catch(ClassNotFoundException cnfex){
cnfex.printStackTrace();
}
}


Código (java) [Seleccionar]
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");

ser.escribirArchivo(yo);
ser.escribirArchivo(prima);

ser.leerArchivo("objeto.mio");

}
}
Lo que faltaba en internet: http://binar10s.blogspot.com/

@rkimedes

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 (java) [Seleccionar]


import java.io.*;
import java.util.HashMap;
import java.util.Map;

public class Serializador{
// Escribe un objecto en un archivo
private ObjectOutputStream escritorArchivo = null;

// Lee un objecto que este guardado en un archivo
private ObjectInputStream lectorArchivo = null;

private Map<String, Integer> hashmap = new HashMap<String, Integer>();

private static int con = 0;

// 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")
public void escribirArchivo(Object objeto){
try{
if(escritorArchivo == null)
escritorArchivo = new ObjectOutputStream(new FileOutputStream("objeto.mio"));
escritorArchivo.writeObject(objeto);
hashmap.put(((Contacto)objeto).getNombre(), con++);
} 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;
}

public Object leerArchivo(String rutaArchivo, String nombre) {
Contacto contacto = null;
int contador = 0;
try{
lectorArchivo = new ObjectInputStream(new FileInputStream(rutaArchivo));
if(hashmap.get(nombre)!= null){
int numero = hashmap.get(nombre).intValue();
while(contador <= numero){
contacto = (Contacto) lectorArchivo.readObject();
contador++;
}
System.out.println(contacto.getNombre() + " " + contacto.getApellido() );
}
else{
System.out.println("El nombre no se encuentra en el archivo");
}
lectorArchivo.close();
}catch(EOFException ex)
{
System.out.println("\nFinal de archivo");
}catch (ClassNotFoundException e) {
e.printStackTrace();
}catch (IOException e) {
e.printStackTrace();
}

return contacto;
}
}


Aikanáro Anário

Gracias, mano!

Tengo que estudiar la clase Hashmap para entender mejor.
Lo que faltaba en internet: http://binar10s.blogspot.com/