Objektorientiertes Laden/Speichern aus Binärdateien
-
Hi! Ich habe ein organisatorisches Problem.
Und zwar muss man ja beim Laden/Speichern aus einer Binärdatei immer die Anzahl der Bytes angeben.
z.B.
cTest t; fout.write ((char*)&t, sizeof (t));Die große Frage ist jetzt: was ist wenn ich eine von cTest abgeleitete Klasse laden möchte.
Was wenn die Lade-Funktion gar nicht weiß dass ein cTest2-Objekt zu laden ist sondern nur dass es irgendein von cTest abgeleitetes objekt sein soll.Meine bisherige Lösung:
1. einen Wert auslesen, der in der Datei vor den eigentlichen Daten abgespeichert ist.
Der gibt an, von welchem Datentyp das nachfolgende ist.
2. richtiges Objekt erstellen und ladenfin.read (&iDatatypeFlag, sizeof (int)); cTest* pObjectToLoad = NULL; if (iDatatypeFlag == CLASS_TYPE_TEST2) { pObjectToLoad = new cTest2; fin.read (&t, sizeof (cTest2)); } // else if (iDatatypeFlag == CLASS_TYPE_TEST3) usw. // oder so ähnlich halt.Funktionieren tut das alles aber es kotzt mich an, in einem objektorientierten Code mit Daten-Typ-Flags zu arbeiten.
Ich hab in google nix gefunden ausser Anfänger-Speicher-Tutorials.
Kennt da jemand eine Flag-Freie Lösung?
-
Wirst du im C++ nicht anders hinbekommen.
-
gloebl schrieb:
...Laden/Speichern aus einer Binärdatei ...
.. besser lassen.

(Habe keine Lust, zum 100ten Mal dasselbe zu schreiben ... mal sehen, ob ich auf die Schnelle den Link finde)Gruß,
Simon2.
-
Simon2 schrieb:
gloebl schrieb:
...Laden/Speichern aus einer Binärdatei ...
.. besser lassen.

(Habe keine Lust, zum 100ten Mal dasselbe zu schreiben ... mal sehen, ob ich auf die Schnelle den Link finde)Gruß,
Simon2.
Wenn du schon dabei bist. Jemand hat mal eine Klasse geschrieben, die binäre Ein/Ausgabe wie mit Textfiles verfügbar macht. War +- 1 Woche her.

-
Simon2 schrieb:
gloebl schrieb:
...Laden/Speichern aus einer Binärdatei ...
.. besser lassen.

(Habe keine Lust, zum 100ten Mal dasselbe zu schreiben ... mal sehen, ob ich auf die Schnelle den Link finde)Im prinzip ist binäres Speichern nicht schwerer als nur als Text zu speichern. Wird auch fast überall gemacht, z.B. alle möglichen Header von Bildern, Videos, Musik und die Daten dazu sind sogut wie immer binär, ZIP usw. Text braucht man nur, wenn es Menschen lesen können sollen.
-
boost serialize?!
-
Falls du Serialisierung von MFC-Klassen meinst: Das löst aber nicht mein Problem, dass ich nicht weiß welche Klasse ich beim Laden erzeugen muss. (soweit ich das verstanden hab)
Es scheint auch so zu sein, dass beim Serialisieren jede Klasse ihren eigenen Speichern-/Laden-Code mitbringen muss.
Wenn ich daran denke, dass ich jeder speicherbaren Klasse noch sowas verpassen muss wird mir ganz anders...
-
Boost.Serialization kann das (nebenbei, Klasse ≠ Objekt), man benutzt dafür RTTI (also typeid bzw. dynamic_cast).
-
Scheint trotzdem darauf hinauszulaufen, dass jede Klasse ihre eigene Load/Save-Methode hat, demnach die Klasse selbst vorher bekannt sein muss.
-
Anderes erlaubt das C++-Objektsystem nicht.
-
naja schrieb:
Simon2 schrieb:
gloebl schrieb:
...Laden/Speichern aus einer Binärdatei ...
.. besser lassen.

(Habe keine Lust, zum 100ten Mal dasselbe zu schreiben ... mal sehen, ob ich auf die Schnelle den Link finde)Im prinzip ist binäres Speichern nicht schwerer als nur als Text zu speichern. Wird auch fast überall gemacht, z.B. alle möglichen Header von Bildern, Videos, Musik und die Daten dazu sind sogut wie immer binär, ZIP usw. Text braucht man nur, wenn es Menschen lesen können sollen.
Wir reden offensichtlich von verschiedenen Dingen.
1.) Ich sprach nicht prinzipiell davon, Daten binär abzuspeichern, sondern direkt C++-Typen binär abzuspeichern.
2.) Mein Gegenargument war auch nicht, dass dies "...schwer..." sei (im Gegenteil: Es scheint offenbar so "einfach" zu sein, dass scheinbar jeder das erstmal für eine gute Idee hält). Da Problem, das mir am gravierendsten erscheint, ist die "Unspezifiziertheit" (und damit verbundene Inkompatibilität) des Objektdesigns.
Oder kurz gesagt: Anderer Compiler, andere Compilerversion, andere Compileroptionen, andere Plattform, andere .... => alle Datenfiles fratze!Es gibt noch andere gute Gründe, vom compilerspezifischen Objektdesign zu abstrahieren (sei es nun in ein "menschenlesbares" Protokoll oder ein anderes), aber schon der o.g. überwiegt in 99% der Fälle die Vorteile einer direkten Binärspeicherung.
Gruß,
Simon2.
-
gloebl schrieb:
...Das löst aber nicht mein Problem, dass ich nicht weiß welche Klasse ich beim Laden erzeugen muss...
Mit reinem Standard-C++ wird Dir letztlich nichts Anderes übrig bleiben. Das ist aber auch so nicht so ungewöhlich: Wenn ich Dir jetzt irgendeine Binärdatei names "a876fh" in die Hand drücke, wirst Du auch immense Probleme haben, rauszubekommen, was ich Dir da mitteilen möchte...

Viele Programme bauen deshalb "Kennzeichen" in ihr "Protokoll" (so nenne ich das Format, in dem Daten abgespeichert werden), anhand derer sie feststellen können, ob sie den Inhalt "verstehen" können oder nicht...und genau sowas sind eben "Typkennzeichen".
Was mir noch einfällt: Du kannst natürlich alle Objekte eines Typs in eine eigene Datei ablegen. Dann hast Du Dein Typkennzeichen einfach in den Dateinamen verlegt.EDIT: Hier der Link, den ich gesucht habe: C++-FAQ-Lite: Serialization and Unserialization
gloebl schrieb:
...
Es scheint auch so zu sein, dass beim Serialisieren jede Klasse ihren eigenen Speichern-/Laden-Code mitbringen muss.
Wenn ich daran denke, dass ich jeder speicherbaren Klasse noch sowas verpassen muss wird mir ganz anders...Schlechte Nachricht: Objektserialisierung ist nunmal ein komplexes Geschäft. Wenn Du das bislang vor Dir hergeschoben hast, wird's jetzt natürlich ein wenig mehr als wenn Du das gleich "mitgemacht" hättest.
Gute Nachricht: Eigentlich ist das gar nicht soooo komplex. Ich habe boost::serialize noch nicht genutzt, sondern mache das immer mit den ganz normalen operator<<() und operator>>() (Vorteil IMHO: Damit kann ich sowieso jederzeit meine Objekte ausgeben(einlesen ... sei es nun in/aus Datei oder in/aus der Konsole (cout/cin).Gruß,
Simon2.