Wie kann ich Daten in einer Datei teilweise ändern
-
Hallo Forum,
ich brauche eine Datei mit mehreren logischen Sätzen aus integer- und string-Werten. Dann möchte ich einzelne Werte der Sätze in der Datei ändern. Zu Testzwecken habe ich es mit string-Daten probiert wie in den nachstehenden Funktionen.
Wenn ich nun einen Wert überschreiben will, (z.B: ab Byte 12 in der Länge 6) steht dann in der Datei bis zum Byte 12 lauter Nullen, dann der zu ersetzende Text und der Rest der Daten ist weg. Was muss ich tun damit das funktioniert?
int writeBinaryFile(string path, string& s, int firstByte) { int lastByte = -1; //nächstes Byte od Fehler: -1 ofstream f(path, ios::binary); if (f) { f.seekp(firstByte); f.write((char*)s.c_str(), s.length()); if (f) { lastByte = f.tellp(); f.close(); return lastByte; } } System::Windows::Forms::MessageBox::Show("(writeBinaryFile) Schreib-Fehler!"); f.close(); return lastByte; } /// end func writeBinaryFile int readBinryFile(string path, string& s, int firstByte) { int lastByte = -1; ifstream f(path, ios::binary); if (f) { f.seekg(firstByte); f.read(&s[0], 78); } return lastByte; }
-
Dein Modus zum Öffnen der Datei muss
ios::in | ios::out | ios::binary
sein. Wobei einofstream
schonout
impliziert, das kannst du also auch weglassen. Dasin
mag komisch aussehen, aber macht eben das, was du willst, nämlich das weder die Datei ersetzt (das hast du jetzt), noch angehängt wird. Diese ganzen Kombinationen der Dateimodi sind ein bisschen komisch und unintuitiv. Kommt aus der Frühzeit der Computerprogrammierung. Muss man einfach wissen, logisch herleiten ist schwierig.Sei dir aber bewusst, dass das die Daten an der angesprungenen Stelle überschreibt, nicht einfügt. Einfügen geht nicht.
-
@SeppJ Danke Sepp, auf diese Idee wäre ich nie gekommen, jetzt funktioniert das!
-
Alternativ müßte auch
fstream f(path, ios::binary)
funktionieren, da dieser schon implizitios::in | ios:out
benutzt.Trotzdem ist es eigenartig, daß die Daten gelöscht werden, da es noch
ios::trunc
dafür gibt: ios_base::openmode.
Aber laut Tabelle in std::basic_filebuf<CharT,Traits>::open gibt es nur einen Unterschied, wenn manios::in | ios:out
benutzt - bei nurios::out
oderios:out | ios::binary
wird implizit immerios::trunc
verwendet).PS: Ich habe jetzt auch immer, der Kürze wegen,
ios
geschrieben, auch wennopenmode
eigentlich in der Basisklasseios_base
definiert ist, obwohl es nur alstypedef
definiert ist, s. basic_ios (bzw. ich erinnere mich, daß es in früheren Versionen noch eine vonios_base
abgeleitete Klasse war).
-
@Th69 Ja, das mit fstream habe ich mir auch schon gedacht.
-
um mit Niklaus Wirth (* 15. Februar 1934 in Winterthur; † 1. Januar 2024 in Zürich) zu antworten: Wahlfreier Zugriff (Random Access) findet nicht auf Dateiebene sondern im Hauptspeicher statt. Denn: Dateien sind Sequenzen, sie werden sequentiell gelesen und sequentiell geschrieben.
Das heißt: Lese den Dateiinhalt auf eine zweckmäßige Datenstruktur (Array, Liste, Map o.ä) und bearbeite diese. Anschließend schreibe diese Daten zurück in die Sequenz (Serialize). Die Frage ist also, wie man abstrakte Datentypen in Sequenzen serialisiert und umgekehrt. Und aus OOP-Sicht könnte man die Daten im RAM als Objekte auffassen die dafür ihre eigenen Methoden bescheiben.
MFG