Foros del Web » Programación para mayores de 30 ;) » Java »

[SOLUCIONADO] Quisiera leer todos los objetos guardados en un archivo .bin

Estas en el tema de Quisiera leer todos los objetos guardados en un archivo .bin en el foro de Java en Foros del Web. Hola. Estoy intentando leer todos los objetos de tipo vehículo que anteriormente he guardado en un archivo .bin. El caso es que solo consigo leer ...
  #1 (permalink)  
Antiguo 03/11/2014, 06:22
 
Fecha de Ingreso: octubre-2012
Mensajes: 45
Antigüedad: 11 años, 6 meses
Puntos: 2
Quisiera leer todos los objetos guardados en un archivo .bin

Hola.
Estoy intentando leer todos los objetos de tipo vehículo que anteriormente he guardado en un archivo .bin.

El caso es que solo consigo leer uno y no encuentro la manera de se muestren todos.
Pongo el código para que se entienda mejor.

Clase vehiculo:

Código:
public class vehiculo implements java.io.Serializable{

	//Variables
	private String marca;
	private String modelo;
	private int potencia;
	private String matricula;
	private  String color;
	
	//Constructor
	public vehiculo(){
		
	}
	public vehiculo(String marca, String modelo, int potencia,
			String matricula, String color) {
		super();
		this.marca = marca;
		this.modelo = modelo;
		this.potencia = potencia;
		this.matricula = matricula;
		this.color = color;
	}

	//Getters & setters
	public String getMarca() {
		return marca;
	}

	public void setMarca(String marca) {
		this.marca = marca;
	}

	public String getModelo() {
		return modelo;
	}

	public void setModelo(String modelo) {
		this.modelo = modelo;
	}

	public int getPotencia() {
		return potencia;
	}

	public void setPotencia(int potencia) {
		this.potencia = potencia;
	}

	public String getMatricula() {
		return matricula;
	}

	public void setMatricula(String matricula) {
		this.matricula = matricula;
	}

	public String getColor() {
		return color;
	}

	public void setColor(String color) {
		this.color = color;
	}
	
	
	
}
Clase main: contiene un menú por acabar.
Código:
import java.io.EOFException;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.Scanner;

public class main {

	public static int option() {
		Scanner scanner = new Scanner(System.in);
		int opt = scanner.nextInt();
		// System.out.println(opt);
		return opt;
	}

	public static void menu() throws IOException {
		boolean exit = false;
		do {
			System.out.println("Selecciona una opcion (solo números 1-3)");
			System.out.println("1-Insertar nuevo coche");
			System.out.println("2-Mostrar lista de coches");
			System.out.println("3-Salir");

			switch (option()) {
			case 1:
				// Insertar nuevo coche
				System.out.println("Define la marca");				
				vehiculo coche=new vehiculo();	
				Scanner scanner = new Scanner(System.in);	
				String marca = scanner.next();		
				coche.setMarca(marca);
				System.out.println("Define el modelo");
				String modelo = scanner.next();
				coche.setModelo(modelo);
				System.out.println("Define la potencia");
				int potencia = scanner.nextInt();
				coche.setPotencia(potencia);
				System.out.println("Define la matrícula");
				String matricula = scanner.next();
				coche.setMatricula(matricula);
				System.out.println("Define el color");
				String color = scanner.next();				
				coche.setColor(color);
				
				setVehiculo(coche);
				
				break;
			case 2:
				// Mostrar lista de coches
				break;
			case 3:
				// Salir
				exit = true;
				break;
			default:
				System.out.println("Nothing to do here");
			}
		} while (exit == false);

	}

	//Graba en el fichero .bin
	public static void setVehiculo(vehiculo vehiculo) throws IOException{
		FileOutputStream fos = new FileOutputStream("fichero.bin",true);
		ObjectOutputStream out = new ObjectOutputStream(fos);			
		out.writeObject(vehiculo);
		out.close();
	}
	
	public static void main(String[] args) throws IOException, ClassNotFoundException {
		// TODO Auto-generated method stub

		menu();

		 FileInputStream fis = new FileInputStream("fichero.bin");

		 try {
			 
			 ObjectInputStream in = new ObjectInputStream(fis);
			  while (true) {
			    vehiculo vehiculo;
			    try {
			      vehiculo = (vehiculo) in.readObject();
			    } catch (EOFException e) {
			    	System.out.println(e);
			      break;
			    }
			    System.out.println(vehiculo.getMarca());
			  }
			} finally {
				fis.close();
			}
	}
}
La idea es que ahora mismo debería de poder mostrar las marcas de todos los vehículos guardados.

Sin embargo obtengo en la salida el primer objeto y un error:

Código:
Seat
Exception in thread "main" java.io.StreamCorruptedException: invalid type code: AC
	at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1379)
	at java.io.ObjectInputStream.readObject(ObjectInputStream.java:371)
	at main.main(main.java:86)
No creo que sea muy complicado, pero no veo el fallo.
  #2 (permalink)  
Antiguo 03/11/2014, 06:59
Avatar de chuidiang
Colaborador
 
Fecha de Ingreso: octubre-2004
Mensajes: 3.774
Antigüedad: 19 años, 6 meses
Puntos: 454
Respuesta: Quisiera leer todos los objetos guardados en un archivo .bin

Hola:

Cuando creas un ObjectOuptutStream, java escribe unos bytes de cabecera en él. Luego puedes escribir objetos.

Cuando creas un ObjectInputStream, java intenta leer unos bytes de cabecera, luego puedes leer objetos.

Por ello, es importante crear ObjectOutputStream al escribir y ObjectInputStream al leer de la misma forma, para que las cabeceras se escriban/lean igual. Me explico.

Si creas un ObjectOutputStream para escribir cada objeto (es lo que haces en el metodo setVehiculo()), en el fichero estas escribiendo cabecera de bytes, objeto, cabecera de bytes, objeto, cabecera de bytes, objeto...

Para leer, debes leer igual, crear un ObjectInputStream para cada objeto que quieras leer, de forma que leas cabecera de bytes, objeto, cabecera de bytes, objeto, ... No lo estás haciendo así, en el metodo main() estás creando un único ObjectInputStream e intentando leer todos los objetos, es decir, estás intentando leer cabecera de bytes, objeto, objeto, objeto, ... El resultado es el StreamCorruptedException.

Más detalles en http://www.chuidiang.com/java/ficher...tosFichero.php

Se bueno.
__________________
Apuntes Java
Wiki de Programación
  #3 (permalink)  
Antiguo 03/11/2014, 07:14
Avatar de Profesor_Falken  
Fecha de Ingreso: agosto-2014
Ubicación: Mountain View
Mensajes: 1.323
Antigüedad: 9 años, 8 meses
Puntos: 182
Respuesta: Quisiera leer todos los objetos guardados en un archivo .bin

Buenas,

Estas guardando un solo objeto en el fichero y no una lista de objetos.

Una lista de vehiculos seria:
List<vehiculo> vehiculos = new ArrayList<>();

Luego estas recorriendo los objetos haciendo un... while(true)???? por lo que tras leer el primero, trata de leer el siguiente y te da un error.

Por otro lado, intenta respetar las reglas de nomenclatura de java. El nombre de las clases debe comenzar siemre en mayusculas:
http://www.oracle.com/technetwork/ja...35099.html#367


Un saludo
__________________
If to err is human, then programmers are the most human of us
  #4 (permalink)  
Antiguo 03/11/2014, 08:18
 
Fecha de Ingreso: octubre-2012
Mensajes: 45
Antigüedad: 11 años, 6 meses
Puntos: 2
Respuesta: Quisiera leer todos los objetos guardados en un archivo .bin

Hola chuidiang.

Cita:
Para leer, debes leer igual, crear un ObjectInputStream para cada objeto que quieras leer, de forma que leas cabecera de bytes, objeto, cabecera de bytes, objeto, ... No lo estás haciendo así, en el metodo main() estás creando un único ObjectInputStream e intentando leer todos los objetos, es decir, estás intentando leer cabecera de bytes, objeto, objeto, objeto, ... El resultado es el StreamCorruptedException.
Haciendo ese cambio casi sale.

Código:
...
		 FileInputStream fis = new FileInputStream("fichero.bin");

		 try {
			 
			  while (true) {
			    ObjectInputStream in = new ObjectInputStream(fis);
			    vehiculo vehiculo;
			    try {
			      vehiculo = (vehiculo) in.readObject();
			    } catch (EOFException e) {
			    	System.out.println(e);
			      break;
			    }
			    System.out.println(vehiculo.getMarca());
			  }
			} finally {
				fis.close();
			}
Obtengo por respuesta:

Código:
FordException in thread "main" 
Seat
java.io.EOFException
	at java.io.ObjectInputStream$PeekInputStream.readFully(ObjectInputStream.java:2328)
	at java.io.ObjectInputStream$BlockDataInputStream.readShort(ObjectInputStream.java:2797)
	at java.io.ObjectInputStream.readStreamHeader(ObjectInputStream.java:802)
	at java.io.ObjectInputStream.<init>(ObjectInputStream.java:299)
	at main.main(main.java:101)
Como se ve, me saca el Ford y el Seat, pero con errores.
Debe haber algo más...

Profesor_Falken: Los objetos que escribo no son para escribirlos todos de una, si no para hacerlo en distintas ejecuciones del código.
Al hacer xxd fichero.bin en el terminal me da a entender que existen dos objetos, o eso creo, pues aumenta al grabar nuevos objetos.
Código:
0000000: aced 0005 7372 0008 7665 6869 6375 6c6f  ....sr..vehiculo
0000010: 3a86 0bf8 279f 6677 0200 0549 0008 706f  :...'.fw...I..po
0000020: 7465 6e63 6961 4c00 0563 6f6c 6f72 7400  tenciaL..colort.
0000030: 124c 6a61 7661 2f6c 616e 672f 5374 7269  .Ljava/lang/Stri
0000040: 6e67 3b4c 0005 6d61 7263 6171 007e 0001  ng;L..marcaq.~..
0000050: 4c00 096d 6174 7269 6375 6c61 7100 7e00  L..matriculaq.~.
0000060: 014c 0006 6d6f 6465 6c6f 7100 7e00 0178  .L..modeloq.~..x
0000070: 7000 0001 f474 0004 526f 6a6f 7400 0346  p....t..Rojot..F
0000080: 6f72 7400 0952 2d33 3433 342d 6c66 7400  ort..R-3434-lft.
0000090: 0546 6f63 7573 aced 0005 7372 0008 7665  .Focus....sr..ve
00000a0: 6869 6375 6c6f 3a86 0bf8 279f 6677 0200  hiculo:...'.fw..
00000b0: 0549 0008 706f 7465 6e63 6961 4c00 0563  .I..potenciaL..c
00000c0: 6f6c 6f72 7400 124c 6a61 7661 2f6c 616e  olort..Ljava/lan
00000d0: 672f 5374 7269 6e67 3b4c 0005 6d61 7263  g/String;L..marc
00000e0: 6171 007e 0001 4c00 096d 6174 7269 6375  aq.~..L..matricu
00000f0: 6c61 7100 7e00 014c 0006 6d6f 6465 6c6f  laq.~..L..modelo
0000100: 7100 7e00 0178 7000 0000 3c74 0008 416d  q.~..xp...<t..Am
0000110: 6172 696c 6c6f 7400 0453 6561 7474 0009  arillot..Seatt..
0000120: 522d 3334 3335 2d70 6f74 0006 4d69 6269  R-3435-pot..Mibi
0000130: 7a61                                     za
Edito: chuidiang, he probado con el asunto de
Código:
protected void writeStreamHeader() throws IOException
{
// No hacer nada.
}
pero el resultado no cambia.

Última edición por yafuslae; 03/11/2014 a las 08:29 Razón: Más info.
  #5 (permalink)  
Antiguo 03/11/2014, 08:39
Avatar de chuidiang
Colaborador
 
Fecha de Ingreso: octubre-2004
Mensajes: 3.774
Antigüedad: 19 años, 6 meses
Puntos: 454
Respuesta: Quisiera leer todos los objetos guardados en un archivo .bin

Hola:

Te está saltando un EOFException, que es normal cuando llegas al final de fichero, parece que la tienes controlada.
¿Cual es la línea main.main(main.java:101)?

Se bueno.
__________________
Apuntes Java
Wiki de Programación
  #6 (permalink)  
Antiguo 03/11/2014, 08:43
 
Fecha de Ingreso: octubre-2012
Mensajes: 45
Antigüedad: 11 años, 6 meses
Puntos: 2
Respuesta: Quisiera leer todos los objetos guardados en un archivo .bin

Linea 101:
Código:
ObjectInputStream in = new ObjectInputStream(fis);
Tengo la sospecha de que es algo de que se escriben cabeceras para cada objeto y no solo al inicio del archivo.
Los objetos pueden ser grabados en varias ejecuciones del código o cada vez que entra al menú. No obstante, cada vez que entra al menú a grabar un objeto nuevo creo que se crean cabeceras igualmente. Estoy convencido de que el fallo va por ahí según lo visto en http://www.chuidiang.com/java/ficher...tosFichero.php

Última edición por yafuslae; 03/11/2014 a las 08:53 Razón: Sospechando
  #7 (permalink)  
Antiguo 03/11/2014, 09:12
Avatar de Profesor_Falken  
Fecha de Ingreso: agosto-2014
Ubicación: Mountain View
Mensajes: 1.323
Antigüedad: 9 años, 8 meses
Puntos: 182
Respuesta: Quisiera leer todos los objetos guardados en un archivo .bin

Buenas,

Yo no veo ningun fallo. Estas llegando al final de fichero, por lo que te esta saltando la EOFException.
El problema es que estas imprimiendo la excepcion. Bastaria con dejarlo asi:

Código Java:
Ver original
  1. try {
  2.                   vehiculo = (vehiculo) in.readObject();
  3.                 } catch (EOFException e) {
  4.                   break;
  5.                 }

Un saludo
__________________
If to err is human, then programmers are the most human of us
  #8 (permalink)  
Antiguo 03/11/2014, 09:16
Avatar de chuidiang
Colaborador
 
Fecha de Ingreso: octubre-2004
Mensajes: 3.774
Antigüedad: 19 años, 6 meses
Puntos: 454
Respuesta: Quisiera leer todos los objetos guardados en un archivo .bin

Es lo que te he comentado, cada vez que haces un new ObjectOutputStream, por el mero hecho de hacer el new, se escribe una cabecera. Cada vez que haces un new ObjectInputStream, por el mero hecho de hacerlo, se intenta leer una cabecera.

Así que o bien tomas la política de hacer un único ObjectOuputStream y un único ObjectInputStream al principio y reutilizarlo siempre, o bien haces un new de cada cada vez que intentas escribir o leer un fichero.

En cualquier caso, lo que tienes es normal. Estás leyendo (new ObjectInputStream) hasta que salte un EOFException, así que el EOF salta. Igual lo que tienes que hacer es no sacarlo por pantalla y hacer el break que estás haciendo.

Se bueno.
__________________
Apuntes Java
Wiki de Programación
  #9 (permalink)  
Antiguo 03/11/2014, 10:15
 
Fecha de Ingreso: octubre-2012
Mensajes: 45
Antigüedad: 11 años, 6 meses
Puntos: 2
Respuesta: Quisiera leer todos los objetos guardados en un archivo .bin

He quitado el
Código:
System.out.println(e);
pero sigue dando el mismo problema.
  #10 (permalink)  
Antiguo 03/11/2014, 10:57
Avatar de chuidiang
Colaborador
 
Fecha de Ingreso: octubre-2004
Mensajes: 3.774
Antigüedad: 19 años, 6 meses
Puntos: 454
Respuesta: Quisiera leer todos los objetos guardados en un archivo .bin

Mete esto

ObjectInputStream in = new ObjectInputStream(fis);

dentro del try/catch.

Se bueno.
__________________
Apuntes Java
Wiki de Programación
  #11 (permalink)  
Antiguo 03/11/2014, 11:04
Avatar de Profesor_Falken  
Fecha de Ingreso: agosto-2014
Ubicación: Mountain View
Mensajes: 1.323
Antigüedad: 9 años, 8 meses
Puntos: 182
Respuesta: Quisiera leer todos los objetos guardados en un archivo .bin

Buenas,

Yo te propongo quitar ese while(true) y esos try/catch y controlar correctamente cuando hay objetos en el stream.


Código Java:
Ver original
  1. public static void main(String[] args) throws IOException, ClassNotFoundException {
  2.         // TODO Auto-generated method stub
  3.  
  4.         menu();
  5.  
  6.         FileInputStream fis = new FileInputStream("fichero.bin");
  7.  
  8.         try {
  9.             vehiculo vehiculo;
  10.             while (fis.available() > 0) {
  11.                 ObjectInputStream in = new ObjectInputStream(fis);
  12.                 vehiculo = (vehiculo) in.readObject();
  13.                 System.out.println(vehiculo.getMarca());
  14.             }
  15.         } finally {
  16.             fis.close();
  17.         }
  18.     }

Creo que asi es mucho mas simple y provoca menos errores

Un saludo
__________________
If to err is human, then programmers are the most human of us
  #12 (permalink)  
Antiguo 10/11/2014, 06:37
 
Fecha de Ingreso: octubre-2012
Mensajes: 45
Antigüedad: 11 años, 6 meses
Puntos: 2
Respuesta: Quisiera leer todos los objetos guardados en un archivo .bin

He aplicado la solución de Profesor_Falken y he conseguido mi objetivo. Muchas gracias a los dos.

Etiquetas: lectura, objetos, serializable
Atención: Estás leyendo un tema que no tiene actividad desde hace más de 6 MESES, te recomendamos abrir un Nuevo tema en lugar de responder al actual.
Respuesta




La zona horaria es GMT -6. Ahora son las 22:39.