Java - Ayuda con Objectoutputstream!!

 
Vista:

Ayuda con Objectoutputstream!!

Publicado por Ana (35 intervenciones) el 30/08/2021 18:19:01
Hola. Buenas tardes, estoy haciendo un ejercicio con persistencia. Y tengo problemas para grabar los objetos en un archivo. Voy agregando los objetos de a uno, ya que tengo un menu. Cuando agrego el primer objeto se lee bien, pero cuando agrego el segundo ya no se lee ninguno. Nose que estoy haciendo mal


public class MiObjectOutputStream extends ObjectOutputStream{ //clase q hereda de objectoutputstream para no sobreescribir la cabecera

public void writeStreamHeader() {
//nada
}

public MiObjectOutputStream() throws IOException {
super();
}

public MiObjectOutputStream (FileOutputStream fileOutputStream) throws IOException {
// TODO Auto-generated constructor stub
super(fileOutputStream);
}

}


//Los metodos guardar y recuperar estan en otra clase

public void guardar (Jugador j) throws IOException {
File f= new File("jugador.objeto");
if( f.exists()){
MiObjectOutputStream salida= new MiObjectOutputStream(new FileOutputStream(f));
salida.writeObject(j);
salida.close();
} else {
ObjectOutputStream salida= new ObjectOutputStream(new FileOutputStream(f,true));
salida.writeObject(j);
salida.close();
}


}

public void recuperar() throws FileNotFoundException, IOException, EOFException, ClassNotFoundException {
ObjectInputStream entrada=null;
try{ entrada = new ObjectInputStream(new FileInputStream("jugador.objeto"));

while (true) {
Jugador j = ( Jugador) entrada.readObject();
System.out.println(j.getNombre());



}
} catch(IOException io){
} finally {
try {
entrada.close();
} catch (Exception exp) {
}


}
Valora esta pregunta
Me gusta: Está pregunta es útil y esta claraNo me gusta: Está pregunta no esta clara o no es útil
0
Responder
Imágen de perfil de Kabuto
Val: 3.428
Oro
Ha mantenido su posición en Java (en relación al último mes)
Gráfica de Java

Ayuda con Objectoutputstream!!

Publicado por Kabuto (1381 intervenciones) el 30/08/2021 20:12:52
Hola.
Como ya comentamos en este otro tema, grabar objetos por separado en un archivo, puede ser problemático.

Veo que has intentado aplicar lo de que no escriba cabecera.
1
2
3
public void writeStreamHeader() {
//nada
}

Pero asegúrate de que escribes su "firma" exactamente igual que la del método que quieres sobreescribir. Porque si no es exactamente igual, puede que los estés "sobrecargando", pero no "sobreescribiendo".
Incluso añádele la etiqueta @Override. Con ella le estás diciendo a Java que tu deseo es sobreescribir ese método y entonces Java comprobará si lo estás consiguiendo. Si no es el caso (porque la "firma" no es correcta quizás...) te saldrá un error avisándote de que no estás sobreescribiendo.

Creo que la firma original es esta:
1
2
3
4
@Override
protected void writeStreamHeader() throws IOException {
//nada
}


Si continúa fallando, puedes probar a establecer el OutputStream como atributo de clase, de manera que NUNCA se cerrará durante la ejecución del programa.
Es decir, ahora mismo tu OutputStream, se abre y se cierra cada vez que llamas al método guardar()
Cada vez que se abre, es cuando escribe una cabecera en el archivo, y eso es lo que provoca que luego no puedas recuperar todos los objetos.

Así que puedes probar a declararlo como atributo de clase, de forma que sea visible para el método guardar() sin que este tenga que abrirlo ni cerrarlo.
Y así permanecerá abierto hasta que el programa termine.


Y si nada de esto funciona, pues solo se me ocurre recomendarte lo que ya te recomendé la otra vez.
Almacenar los objetos en un array, ArrayList, o cualquier otra colección... y de esta manera solo tendrás que escribir en el archivo un único objeto, que en realidad contendrá varios en su interior.

Es decir, en lugar de escribir varios objetos Jugador, solo tendrás que escribir un objeto ArrayList<Jugador>
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar

Ayuda con Objectoutputstream!!

Publicado por Ana (35 intervenciones) el 30/08/2021 22:17:05
Hola. Gracias! lo hice, pero no funciona.

Como tendria que hacer para ir agregando los objetos al array? tendria que recuperar el array que esta en el fichero y agregar en la ultima posicion el nuevo objeto? No se me ocurre como hacerlo y es la primera vez que trabajo con ficheros
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar
Imágen de perfil de Kabuto
Val: 3.428
Oro
Ha mantenido su posición en Java (en relación al último mes)
Gráfica de Java

Ayuda con Objectoutputstream!!

Publicado por Kabuto (1381 intervenciones) el 31/08/2021 01:56:42
Como los Jugadores van a ir aumentando, lo ideal es usar un ArrayList que puede ir creciendo según se le añaden objetos.

Entonces, tendrías que declarar el ArrayList como atributo de clase, para que sea de ámbito global y visible para cualquier otro método.
1
2
3
4
5
6
7
8
9
public class TuClase {
    ArrayList<Jugador listaJugadores = new ArrayList<Jugador>();
 
    public TuClase() {
        //Constructor
    }
 
    //Resto de métodos....
}

Así, cuando se evoque el método guardar(), pues primero meter el jugador en el ArrayList y luego escribes el ArrayList en disco.
A los constructores de los FileOutputStream no le indiques nada para el atributo boolean. O si quieres asegurarte de que cada vez que escribas, NO van a añadir un nuevo objeto al final del archivo, indícales false. Pero vamos, si no indicas nada, es como poner false.
De este modo, cada vez que escribas un objeto, sustituirá al anterior que hubiera guardado, que es lo que queremos.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public void guardar (Jugador j) throws IOException {
 
    listaJugadores.add(j);
 
    File f= new File("jugador.objeto");
    if( f.exists()){
        MiObjectOutputStream salida= new MiObjectOutputStream(new FileOutputStream(f, false));
        salida.writeObject(listaJugadores);
        salida.close();
    } else {
        ObjectOutputStream salida= new ObjectOutputStream(new FileOutputStream(f, false));
        salida.writeObject(listaJugadores);
        salida.close();
    }
}

Por cierto, puede que ya no necesites la clase "personalizada" MiObjectOutputStream, pero lo he dejado tal cuál lo tienes el método para hacer los cambios mínimos.
Si consigues que te funcione, ya tu misma readaptas el código para eliminar lo que ya no sea necesario.

Luego, para recuperar.
Ahora solo has de leer UN objeto. Y castearlo a ArrayList<Jugador>
Puede que tu entorno de desarrollo(IDE), te muestre un warning en la línea donde haces el casting a ArrayList.
No es un error, es un "aviso" que suele indicar que quizás deberías hacer alguna comprobación extra antes de atreverte a hacer un casting a un tipo tan concreto de ArrayList.
Pero no importa, si te aparece ese aviso, ignóralo. En este ejercicio tienes la seguridad 100% de que lo que vas a leer es un objeto ArrayList<Jugador>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public void recuperar() throws FileNotFoundException, IOException, EOFException, ClassNotFoundException {
    ObjectInputStream entrada=null;
    try{
        entrada = new ObjectInputStream(new FileInputStream("jugador.objeto"));
        listaJugadores = (ArrayList<Jugador>) entrada.readObject();
        //Si ha ido bien, ya hemos recuperado los Jugadores, mostramos sus nombres en pantalla
        System.out.println("Jugadores recuperados: " + listaJugadores.size());
        for (Jugador j: listaJugadores) {
            System.out.println(l.getNombre());
        }
    }
    catch(IOException io){
    } finally {
        try {
            entrada.close();
        } catch (Exception exp) {
    }
}


A ver si de esta manera te funciona. No se si en el resto del programa tendrás que hacer más cambios por estar usando un ArrayList que antes no usabas. Eso ya lo verás tú misma.
Un saludo.
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar

Ayuda con Objectoutputstream!!

Publicado por Ana (35 intervenciones) el 07/09/2021 21:12:40
Hola. muchas gracias! Me guarda bien los objetos en el archivo. Pero cuando los quiero recuperar no recupera ninguno.
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar

Ayuda con Objectoutputstream!!

Publicado por Ana (35 intervenciones) el 07/09/2021 21:30:17
Noto que cuando el archivo tiene dos objetos cuando ejectura el metodo recuperar no entra al try

String ganadoress="";
ObjectInputStream entrada=null;
System.out.println("antes del try");
try{
entrada = new ObjectInputStream(new FileInputStream("jugador7.dat"));

System.out.println("Entro");
ganadores = (ArrayList<Jugador>) entrada.readObject();
for (Jugador j: ganadores) {
System.out.println("for");
System.out.println(j.getNombre());

}
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar
Imágen de perfil de Kabuto
Val: 3.428
Oro
Ha mantenido su posición en Java (en relación al último mes)
Gráfica de Java

Ayuda con Objectoutputstream!!

Publicado por Kabuto (1381 intervenciones) el 09/09/2021 12:49:14
Pues no se a que se debe...

Mira, he hecho una versión muy simplificada, pero que en esencia es lo mismo.
Clase Jugador (inventada por mi):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
import java.io.Serializable;
 
public class Jugador implements Serializable {
 
	private String nombre;
	private int numero;
 
	public Jugador(String nombre, int numero) {
		this.nombre = nombre;
		this.numero = numero;
	}
 
	public String getNombre() {
		return nombre;
	}
 
	public void setNombre(String nombre) {
		this.nombre = nombre;
	}
 
	public int getNumero() {
		return numero;
	}
 
	public void setNumero(int numero) {
		this.numero = numero;
	}
 
	@Override
	public String toString() {
		return String.format("Nombre %s -- Numero: %d", nombre, numero);
	}
 
}

Luego una clase que gestiona un ArrayList de Jugadores, con un método para añadir jugador al ArrayList y guardarlo en disco.
Y otro para recuperar el ArrayList guardado.
En el constructor de esta clase, hago que comience intentando recuperar el archivo guardado.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.ArrayList;
 
public class GestionJugadores {
 
	private ArrayList<Jugador> jugadores;
 
	public GestionJugadores() {
		recuperar();
	}
 
	public void mostrarJugadores() {
		System.out.println("\n\tJUGADORES");
		System.out.println("\t---------");
		for (Jugador j: jugadores)
			System.out.println(j);
	}
 
	public void guardar(Jugador j) {
		jugadores.add(j);
		try {
			ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("jugadores.dat"));
			oos.writeObject(jugadores);
			oos.close();
		} catch (Exception e) {
			System.out.println("Error: " + e.getMessage());
		}
	}
 
	public void recuperar() {
 
		try {
			ObjectInputStream ois = new ObjectInputStream(new FileInputStream("jugadores.dat"));
			jugadores = (ArrayList<Jugador>) ois.readObject();
			ois.close();
			System.out.println("Jugadores recuperados: " + jugadores.size());
			mostrarJugadores();
		} catch (Exception e) {
			System.out.println("Error: " + e.getMessage());
			System.out.println("No se pudieron recuperar Jugadores. ArrayList comienza vacio");
			jugadores = new ArrayList<Jugador>();
		}
	}
}

Y una clase main() que inicializa un objeto de esta clase que gestiona el ArrayList.
Al inicializar recupera los jugadores guardados (si los hay) y los muestra.
Luego ofrece añadir un nuevo jugador y se termina el programa.

Así puede verse que cada vez que iniciamos el programa, la lista de jugadores va aumentando:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import java.util.Scanner;
 
public class Main {
 
	private static GestionJugadores gestor;
	private static Scanner teclado;
 
	public static void main(String[] args) {
		gestor = new GestionJugadores();
		teclado = new Scanner(System.in);
 
		System.out.println("\nNuevo jugador...");
		System.out.print("Nombre: ");
		String nombre = teclado.nextLine();
		System.out.print("Numero: ");
		int numero = Integer.parseInt(teclado.nextLine());
 
		gestor.guardar(new Jugador(nombre, numero));
	}
 
}


Es un programa muy simple, pero muestra cómo guardar y leer un ArrayList serializándolo como un Object.
Tu código será más complejo, pero lo de guardar y leer debería ser prácticamente lo mismo.

A ver si te sirve como inspiración para detectar en que puedes estar fallando tu programa.
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar