Objekte binär in Datei abspeichern

HCWD

Erfahrenes Mitglied
Hi Ho liebe Community,

nach langer Pause habe ich wieder eine kleine Wissenslücke bei mir gefunden, welche in einfach nicht gebacken bekommen, obwohl ich schon 2 Tage lang dannach google.

ich möchte ein von mir erstelltes Objekt in einer Datei binär abspeichern... Alles schön und gut.

Meine Lösung war über ein new ObjectOutputStream(new FileOutputStream(file)); dies zu lösen.

Mein Problem ist jetzt, wie bekomme ich das wieder in ein Objekt eingelesen, da das simple readObject() nicht funktioniert.

Könntet Ihr mir da paar Tipps oder Vorschläge geben und vielleicht erklären, wieso das so sein soll und nicht anders?

Greetz
HCWD
 
ist bissl primitiv der code, aber nehme sehr gern kritik und verbesserungsvorschläge für die zukunft entgegen :)

Code:
import java.io.*;

public class Function {
	
	private File root;
	private File save;
	private ObjectOutputStream out;
	private ObjectInputStream in;
	
	public Function(String dataname)
	{
		root = new File("./save/");
		if(!root.exists())
			root.mkdir();
		
		save = new File(root,dataname+".sdh");
		
		try{
			if(!save.exists())
				save.createNewFile();
			
			out = new ObjectOutputStream(new FileOutputStream(save));
			in = new ObjectInputStream(new FileInputStream(save));
		}
		catch(IOException e)
		{
			System.out.println("[ERROR] Datei \""+dataname+".sdh\" konnte nicht zum Schreiben oder Lesen vorbereitet werden!");
		}
	}
	
	public boolean save(Schedule schedule)
	{
		try{
			out.writeObject(schedule);
			out.close();
			return true;
		}
		catch(Exception e)
		{
			System.out.println("Fehler beim Speichern des Obejctes!");
			return false;
		}
	}
	
	public Object load()
	{
		try{
			return in.readObject();
		}
		catch(Exception e)
		{
			System.out.println("Fehler beim Auslesen des Objektes!");
			return null;
		}
	}
}
 
Was ist denn der Fehler? Schaut was ich so sehe gut aus, hab gestern auch damit rumprobiert und war in etwa so, außer dass ich dem In-/Outputstream von Sockets verwendet habe. Ist Schedule die Klasse, die du (De)Serialisieren willst? Hast du das entsprechende Interface implementiert? Enthält das Object nicht serialisierbare Dinge? (Wie Threads, Sockets ect.). Steht in der jeweiligen Datei überhaupt etwas drinnen? Gib mal dem StackTrace der Exception aus. (e.printStackTrace()).

Ich würde root zur Final machen und direkt bei der Deklaration setzen. Dann out und in erst in den Methoden deklarieren und füllen. Dann eine Methode schreiben, die als Parameter dem größten gemeinsamen Teiler von OOS und OIS erwartet. (Ich glaube eh InputStream), und diesen schließt. In die beiden Methoden würde ich an das try/catch noch ein finally hängen, was das 2. try/catch des closed() aus dem Source zu haben. Natürlich muss er dann das gelesene zwischenspeichern, da finally ja dem returnwert überschreibt. Und in der save würde ich als Parameter ein Object erwarten lassen, dann kannst du jede beliebige Klasse verwenden, die über die Möglichkeit verfügt. Casten musst du nach dem Lesen sowieso.
 
Was ist denn der Fehler? Schaut was ich so sehe gut aus, hab gestern auch damit rumprobiert und war in etwa so, außer dass ich dem In-/Outputstream von Sockets verwendet habe. Ist Schedule die Klasse, die du (De)Serialisieren willst? Hast du das entsprechende Interface implementiert? Enthält das Object nicht serialisierbare Dinge? (Wie Threads, Sockets ect.). Steht in der jeweiligen Datei überhaupt etwas drinnen? Gib mal dem StackTrace der Exception aus. (e.printStackTrace()).

jop, mach das mal. Ansonsten ist dir eher schlecht zu helfen

Natürlich muss er dann das gelesene zwischenspeichern, da finally ja dem returnwert überschreibt.

check ich jetzt nicht so ... bitte um Ausführungen (kann auch daran liegen, dass der 2.1. ist, und mir Silvester noch in den Knochen hängt ... Frohes Neues, btw ;) ).

Und in der save würde ich als Parameter ein Object erwarten lassen, dann kannst du jede beliebige Klasse verwenden, die über die Möglichkeit verfügt.

Ich würde ein Serializable erwarten. Es können eh nur Objekte gespeichert werden, die Serializable implementieren.
 
Ihr müsst euch einfach vorstellen, es ist ein ganz simpler Stundenplan, dessen Einträge abgespeichert werden sollen und halt beim aufrufen wieder ausgelesen und initialisiert werden sollen. Sockets habe ich noch keine... und mit Threads bin ich noch nicht ganz vertraut. Dieses "Serialisierbare" habe ich nicht ganz verstanden. Musste das Kapitel im Buch übersprungen haben ^^ Könnt ihr kurz ne kleine Erklärung dazu geben?

Ansonsten habe ich mal das ganze nach deinen Tipps angepasst, jedoch der gleiche Fehler weiterhin... Vielleicht wenn ich den Punkt mit "Serialisierbarkeit" verstehe, hilfts dann :)

Ach und die save.sdh datei wurde schon erstellt mit einem abgespeichertem Objekt drin :)

Hier das Ergebnis des StackTrace:
Code:
java.io.EOFException
	at java.io.ObjectInputStream$BlockDataInputStream.peekByte(Unknown Source)
	at java.io.ObjectInputStream.readObject0(Unknown Source)
	at java.io.ObjectInputStream.readObject(Unknown Source)
	at p.Function.load(Function.java:52)
	at p.Runtime.main(Runtime.java:24)

Und um das ganze Vollständig zu haben, habe ich schnell eine angepasste Runtime erstellt, damit Ihr euch auch ein Bild vom Abarbeitungsverlauf machen könnt:

Code:
package p;

import java.io.*;

public class Runtime {

	/**
	 * @param args
	 */
	public static void main(String[] args) throws IOException{
		Function f = new Function("test");
		
		
		Modul pi = new Modul("Praktische Informatik I",1,"Prof 1","Dienstag",5);
		Modul ana = new Modul("Analysis I",1,"Prof 2","Freitag",2);
		/*
		Schedule schedule = new Schedule("Universität ...",1);
		schedule.setSchedule("Dienstag", 5, pi);
		schedule.setSchedule("Freitag", 2, ana);
		
		f.save(schedule);
		*/

			Schedule schedule = (Schedule) f.load();		
	}

}

Hat es vielleicht damit zu tun, dass die Datei-Anordnung getrennt ist?

Das Ganze liegt im Ordner Stundenplan und dort sind 2 Ordner. Einmal der Ordner (Package) p mit den java Dateien und einmal der Ordner Save mit den SDHs... kann er vielleicht darauf nicht bei so einer Anordnung zugreifen?
 
Zuletzt bearbeitet:
public class EOFException
extends IOException

Signals that an end of file or end of stream has been reached unexpectedly during input.

This exception is mainly used by data input streams to signal end of stream. Note that many other input operations return a special value on end of stream rather than throwing an exception.
Bedeutet im Grunde, das er wo lesen will, wo nichts mehr steht. Also kontrolliere die Datei, wo das Object drinnensteht. Oder eventuell einen BufferedReader(FileReader(File("Datei"))) erstellen, und mit ReadLine den Inhalt als String ausgeben lassen, um zu sehen obs der schafft.

Serialisieren bedeutet einfach das was du machen willst: Ein Object als Byte-Code speichern.
http://openbook.galileodesign.de/javainsel5/javainsel12_013.htm#Rxx747java12013040004041F04610B


The_S hat gesagt.:
check ich jetzt nicht so ... bitte um Ausführungen (kann auch daran liegen, dass der 2.1. ist, und mir Silvester noch in den Knochen hängt ... Frohes Neues, btw ;) ).
lol. ^^
Ich weiß, schlechte Wortwahl (vor allem "überschreiben"). Ich meinte einfach nur, dass das Object nicht direkt zurückgegeben werden kann, sondern zwischengespeichert werden muss, da das return im finally oder darunter sitzen muss.
Dir btw. auch.

The_S hat gesagt.:
Ich würde ein Serializable erwarten. Es können eh nur Objekte gespeichert werden, die Serializable implementieren.

Stimmt, vieeeeel besser!
Ich denke selbst nur nie daran, dass man auch mit Interface's Objekte "gruppieren" kann.
 
Also ich habe nun dieses Kapitel ausführlich durchgearbeitet und mit Strings etc. klappt es schön einwandfrei.

Jedoch scheitert es direkt bei einem Objekt, welches ich aus einer eigenen Klasse instanziere. An meinem Beispiel wäre es die Klasse "Schedule". Alle Objekte aus der Klasse lassen sich nicht abspeichern -.-

Weiß jemand vielleicht wieso?

Es hat bestimmt etwas mit dem Serialisieren zu tun, da ich folgende Exception geworfen bekommen: java.io.NotSerializableException: p.Schedule

Da Schedule nicht serialisierbar ist, weiß ich nun aber was genau sagt mir jetzt diese Exception oder wie bekomme ich dieses Problem gelöst?
 
Zuletzt bearbeitet:
Habe das Problem gelöst... Es hat gereicht einfach implements Serializable in die Klasse hinzuzufügen, die schreib-/lese-fähig gemacht werden soll :)

Danke für euere Hilfe :)


EDIT: Noch ein kleines Problem habe ich :)

Bei folgendem Code bekomme ich einwandfrei die Referenz des ausgelesenen Objektes angezeigt:
Code:
Function f = new Function("test");
		
		Modul pi = new Modul("Praktische Informatik I",1,"Prof 1","Dienstag",5);
		Modul ana = new Modul("Analysis I",1,"Prof 2","Freitag",2);
		
		Schedule schedule = new Schedule("Uni...",1);
		schedule.setSchedule("Dienstag", 5, pi);
		schedule.setSchedule("Freitag", 2, ana);
		
		f.save(schedule);
		
		System.out.println(f.load());

Jedoch bei diesem Code bekomme ich wieder diese Exception, dass sich das Ganze überläd, angezeigt:
Code:
Function f = new Function("test");
		
		Modul pi = new Modul("Praktische Informatik I",1,"Prof 1","Dienstag",5);
		Modul ana = new Modul("Analysis I",1,"Prof2","Freitag",2);
		
		System.out.println(f.load());

Was mich zusätzlich wundert ist, dass beim ersten Code, da wo alles einwandfrei läuft, die Datei mit Daten gefüllt wird. Alles schön und gut, jedoch beim Zweiten ist die Datei leer, obwohl ich diese ja nicht überschreibe, sondern nur auslese... oder übersehe ich da etwas?
Wo liegt jetzt darin das Problem?
 
Zuletzt bearbeitet:
Zurück