[C++] Daten in Binärdateien überschreiben

*cerox*

Lt. Commander
Registriert
Feb. 2005
Beiträge
1.357
Hallo zusammen,

ich muss hier ein objektorientiertes Programm schreiben, welches Datensätze in Text- oder Binärdateien speichert (keine Datenbank).

Ich habe mich nun für Binärdateien entschieden, da ich die Daten dort Objekt für Objekt reinschreiben und auslesen kann mit fread und fwrite.

Das funktioniert auch alles soweit wunderbar. Nun möchte ich im Programm die Möglichkeit haben, Datensätze (in dem Fall die Daten eines Objekts) zu ändern. Dazu habe ich das Objekt ausgelesen und geändert. Nun möchte ich das Objekt wieder an die "alte Stelle" schreiben, und so nur die alten nicht mehr benötigten Daten überschreiben.

Ich habe nun versucht, das ganze mit fsetpos und fgetpos zu lösen. Nach dem Auslesen des richtigen Objekts habe ich also geschrieben:

Code:
fgetpos (file,&pos);

- pos ist eine Variable vom Typ fpos_t (das stand so im meinem C-Buch)
- file ist ein Zeiger einer FILE-Struktur

Das richtige Objekt bekomme ich so 100%ig (hab ich mehrmals geprüft) und der Dateipositionszeiger sollte nun am Ende des Objekts stehen, welches ich überschreiben möchte.

Daher wollte ich danach danach den Dateipositionszeiger um ein Objekt zurück setzen mit:

Code:
pos-=sizeof(class kunden);

Den sizeof Operator hab ich auch bei fread und fwrite immer benutzt; die Frage ist nur ob das jetzt so funktioniert, indem ich die Größe einer Klasse von einem Zeiger subtrahiere, denn vorher habe ich nur mit sizeof die Größe angegeben und nicht damit gerechnet; ich denke mal hier liegt der Fehler, denn wenn ich jetzt das Objekt in die Datei schreibe, hängt er es immer wieder hinten an der Datei an, als hätte er den Dateipositionszeiger nie geändert.

Vor dem Schreiben habe ich ihn natürlich gesetzt mit:

Code:
fsetpos(file,&pos);

Kann mir bitte jemand helfen? Ich weiß da nicht mehr weiter...
 
Zuletzt bearbeitet:
Mit dem Überschreiben eines Datensatzes habe ich mich ehrlich gesagt noch nie wirklich befasst, da ich das noch nie gebraucht habe. Wäre es denn tragisch, die Datei einfach neu zu schreiben?

Allerdings - die Objekte binär zu speichern ist eine denkbar schlechte Idee. Die geschriebenen Dateien werden erstmal recht wahrscheinlich nur von einem mit deinem jetzigen Compiler erzeugten Programm wieder lesbar sein. Schon ein Versionswechsel des Compilers kann dir da einen Strich durch die Rechnung machen. Außerdem zerschießt dir jede Änderung an der Klassenhierarchie dein komplettes Dateiformat und macht die alten Dateien unbrauchbar.

Außerdem sollten, wenn du die Informationen nur mit write( objekt, sizeof( objekt)) schreibst, sämtliche Typinformationen verloren gehen. Wenn du nicht genau weißt was du in der Datei erwartest, ist sie nicht zu parsen. Davon abgesehen sollten dir virtuelle Funktionen, virtuelle Vererbung und Mehrfachvererbung einen dicken Strich durch die Rechnung machen.
 
Wäre es denn tragisch, die Datei einfach neu zu schreiben?

Ja, wäre es, da in dieser Binärdatei alles gespeichert wird. Es geht um eine kleine Kundenverwaltung. Ich kann bis jetzt Kunden hinzufügen, mir eine Liste ausgeben lassen und nach Kunden suchen. Was noch fehlt ist die Daten zu ändern.

Allerdings - die Objekte binär zu speichern ist eine denkbar schlechte Idee. Die geschriebenen Dateien werden erstmal recht wahrscheinlich nur von einem mit deinem jetzigen Compiler erzeugten Programm wieder lesbar sein. Schon ein Versionswechsel des Compilers kann dir da einen Strich durch die Rechnung machen. Außerdem zerschießt dir jede Änderung an der Klassenhierarchie dein komplettes Dateiformat und macht die alten Dateien unbrauchba

Das weiß ich, aber da es "nur" ein Schulprojekt ist und ich jetzt schon 1200 Zeilen habe, werde ich wohl nicht noch ein drittes Mal von neu beginnen (beim ersten Mal hatte ich mit Textdateien gearbeitet; da es dann sehr umständlich wurde, alles mit Tilden oder Begrenzer zu trennen, bin ich auf Binärdateien umgestiegen. Klassenändernungen werden nicht vorgenommen - das dann die Datei unbrauchbar ist, ist mir klar.

Es geht jetzt erstmal nur darum, den Dateipositionszeiger zu verschieben; und zwar um die Größe eines Objektes zurück.

So scheint es ja nicht zu gehen:

Code:
pos-=sizeof(class kunden);
 
Einfach nur pos -= sizeof( kunden). :)

Da fällt mir aber noch eines ein. Wenn du die Datei schon bis zum Ende gelesen hast und EOF gesetzt ist, haben die seek-Befehle keine Auswirkung. Du musst erstmal alle Fehlerflags mit void clearerr( FILE *stream ); löschen.

Und hast du mal den Rückgabewert von fsetpos geprüft?
 
Zuletzt bearbeitet:
Wenn du die Datei schon bis zum Ende gelesen hast und EOF gesetzt ist, haben die seek-Befehle keine Auswirkung.

Ich lese die Datensätze Objekt für Objekt in einer while Schleife aus. Diese Schleife bricht ab, wenn der gewünschte Datensatz ausgelesen wurde - d.h. ich bin nicht immer am Dateiende.

fsetpos gibt eine 0 zurück - d.h. das Setzen des Dateipositionszeigers war erfolgreich.

Was darf ich unter einem Fehlerflag verstehen?
 
Ein Fehlerflag signalisiert einfach einen fehlerhaften Streamzustand. Z.B. wenn du versuchst eine nicht-existierende Datei zu öffnen. Oder versuchst zu schreiben wenn die Festplatte voll ist.

Warum bei dir allerdings immer hinten angehängt wird, ist mir jetzt auch nicht 100%ig klar.
 
Poste doch mal die relevanten Codestellen. D.h. öffnen, lesen und schreiben der Datei.

MfG

Arnd
 
Das habe ich zwar teilweise schon getan, aber hier nochmal:

Öffnen der Datei:

Code:
FILE *file=fopen(videodat,"ab+");
fpos_t pos;

Wenn der richtige Datensatz gefunden wurde (es wird also nicht immer das Dateiende erreicht):

Code:
fgetpos (file,&pos);

Der Dateipositionszeiger wird dann zurück verschoben:

Code:
pos-=sizeof(class kunden);

Vor dem Schreiben:

Code:
fsetpos(file,&pos);

fsetpos gibt als Rückgabewert 0 zurück; das Setzen war also erfolgreich.

Trotdem hängt er immer hinten an.

edit:
Boa mist, ich bin so dumm. Ich habe dem sizeof Operator die falsche Klasse übergeben. Trotzdem danke allen^^
 
Zuletzt bearbeitet:
Hallo *cerox*,

deswegen habe ich dich gebeten mehr Code zu posten :-). Nur die Funktionen an sich bringen da nicht viel. Manchmal ist auch der Kontext entscheidend.

MfG

Arnd
 
Ja, da kriegt man echt zu viel. Ich habe den Fehler bestimmt zwei Stunden lang gesucht und mich immer gefragt warum er hinten anhängt.

Obwohl: Warum er hinten anhängt, frage ich mich auch jetzt noch denn vorher hatte ich als Größenangabe bei sizeof die falsche Klasse angegeben; d.h. eigentlich, dass er "kreuz und quer" in die Datei schreiben müsste, wodurch das Programm keinen Kunden mehr korrekt anzeigen könnte.
 

Ähnliche Themen

Zurück
Oben