![]() |
[C++] Binärdateien
Hallo.
ich versuche verzweifelt eine Struktur in einer datei zu speichern und diese wieder auszulesen. Es klappt leider nicht. Ich weiß auch nicht warum! :? vielleicht hab ich ja irgendwas übersehen meine struktur
Code:
meine lesen button
struct info
{ AnsiString Name; AnsiString Strasse; };
Code:
mein schreiben button
ifstream file("testdatei", ios::binary | ios::in);
info nfo; file.read((char*)&nfo, sizeof(nfo)); file.close(); this->Edit1->Text = nfo.Name; this->Edit2->Text = nfo.Strasse;
Code:
ofstream file("testdatei", ios::out | ios::binary); info nfo; nfo.Name = this->Edit1->Text; nfo.Strasse = this->Edit2->Text; file.write((char*)&nfo, sizeof(nfo)); file.close(); |
Re: [C++] Binärdateien
AnsiString ist ein Zeiger auf den String. Die struct enthält somit nur 2 Zeiger (was dir sizeof() mit einem Ergebnis von 8 schon zeigt) und somit speicherst du nur die Adressen, wo die Strings liegen, aber nicht die Zeichenketten selber.
|
Re: [C++] Binärdateien
Zitat:
|
Re: [C++] Binärdateien
Du speicherst die Speicheradresse, an dem der String zum Speicherzeitpunkt steht in die Datei ab, nicht den Inhalt der Zeichenkette.
|
Re: [C++] Binärdateien
Wie könnte ich, dieses Problem umgehen?
vielleicht so, oder *AnsiString dereferzierung auf ansistring |
Re: [C++] Binärdateien
Du willst eine binäre Datei schreiben somit musst du dir über das Dateiformat im klaren sein. Wenn du die Strings einfach so in die Datei schreibst, woher sollte er beim auslesen wissen, was noch der erste String ist und was der zweite? Somit brauchst du ein Format, was du vorher festlegst und dann entsprechend schreiben kannst.
Beispiel: Offset Grösse Inhalt 0 4 Länge nachfolgender String 4 x String selber 4+x 4 Länge nachfolgender String 8+x y String selber Somit:
Code:
ofstream file("testdatei", ios::binary | ios::out);
info nfo; ... int lLen = nfo.Name; file.write(&lLen, sizeof(int)); file.write(nfo.Name.c_str(), lLen); lLen = nfo.Strasse; file.write(&lLen, sizeof(int)); file.write(nfo.Strasse.c_str(), lLen);
Code:
@other: könntet ihr euch mal den Kommentar anschauen??
ifstream file("testdatei", ios::binary | ios::in);
info nfo; ... int lLen(0); file.read(&lLen, sizeof(int)); nfo.Name.SetLength(lLen); file.read(nfo.Name.c_str(), lLen); // ist der temporäre char * auch so rückwärts nutzbar wie in Delphi? file.read(&lLen, sizeof(int)); nfo.Strasse.SetLength(lLen); file.read(nfo.Strasse.c_str(), lLen); // ist der temporäre char * auch so rückwärts nutzbar wie in Delphi? /EDIT: andere Lösung
Code:
Alles ungetester Code, so hier hingeschrieben
ifstream file("testdatei", ios::binary | ios::in);
info nfo; ... int lLen(0); char *buff; file.read(&lLen, sizeof(int)); buff = new char[lLen]; file.read(buff, lLen); nfo.Name = AnsiString(buff); delete buff; file.read(&lLen, sizeof(int)); buff = new char[lLen]; file.read(buff, lLen); nfo.Strasse = AnsiString(buff); delete buff; |
Re: [C++] Binärdateien
hi muetze,
vielen dank für deine Antwort. Ich bin erst vor kurzem auf c++ umgestiegen und ich glaube ich habe da was verwechselt. in delphi hatte ich für das speichern von records typisierte dateien verwendet. -> typisierte dateien sind ja nicht das gleiche wie binäre dateien? kennst du vielleicht irgend ein tutorial, wo das gut erklärt wird? |
Re: [C++] Binärdateien
Zitat:
Typisierte Dateien aus der Pascal Zeit sind nichts anderes, als eine feste Verbändelung einer Struktur und einer Datei. Dabei sagt dieses Konstrukt nur aus: Die Datei ist eine aneinander-Reihung von dieser Struktur. Dadurch rechnen alle Dateiroutinen automatisch diese Struktur in ihren Operationen ein. D.h. Jeder Lesevorgang liest automatisch SizeOf(Struktur) Bytes (also immer soviel Bytes wie die Struktur gross ist) und beim Schreiben gleiches. FileSize() liefert dir die Anzahl, wie oft die Struktur ganz in die Datei reinpasst (also eigentlich: wirkliche Dateigrösse div SizeOf(Struktur) ). Wenn du nun eine Struktur definierst, welche wie deine C struct aussieht, dann hättest du das gleiche Problem:
Delphi-Quellcode:
Mal abgesehen das dich Delphi schon warnt, dass der Typ "file of TMyFileStruct" eine Initialisierung braucht, wirst du hier auf das gleiche Problem stossen wie beim C++Builder: er würde nur 8 Bytes pro Eintrag schreiben und darin sind nur die Adressen der Strings und nicht deren Inhalt. String ist ein Synonym für AnsiString (so lange nicht explizit durch Compileroptionen umgestellt).
type
TMyFileStruct = Record name: string; strasse: string; end; var MyFile: file of TMyFileStruct; Bei C++ gibt es erstmal solche typisierten Dateitypen nicht (nicht grundsätzllich: Mit templates gibs bestimmt auch schon eine Lösung). Du nutzt ja nun in C++ nun die Streams und das kannst du eigentlich mit TFileStream in Delphi vergleichen (mal abgesehen, dass du direkt TFileStream unter dem C++Builder verwenden kannst und sogar direkt eine Delphi Unit einbinden kannst, welcher z.B. den entsprechenden Code enthält. Dann hättest du eine Unit zum Laden und Speichern und der Code wäre im C++Builder Projekt der gleiche wie im Delphi Projekt). Du versuchst nun die Struktur zu Lesen bzw. zu Schreiben. Hier hast du das gleiche Problem wie in Delphi: Die Dateistruktur muss feststehen. Du hast bestimmt früher in Delphi folgendes Konstrukt verwendet:
Delphi-Quellcode:
Damit hast du die Strings von der Länge festgelegt (ShortString = 255 + Längenbyte). Damit war der Record auch 512 Bytes gross - egal wieviel Zeichen im Endeffekt von den Zeichenketten genutzt wurden. Dafür hast du aber auch den Nachteil: Name und Straße kann niemals mehr als 255 Zeichen lang sein. String, AnsiString etc. sind dynamisch und deshalb intern Zeiger auf den Inhalt, welcher sich dann dynamisch anpasst. Damit sind diese Zeichenketten nicht mehr an 255 Zeichen gebunden (im Gegenteil: sie können bis zu 2 GB lang werden).
type
TMyFileStruct = Record name: shortstring; // bzw. string[x] strasse: shortstring; end; var MyFile: file of TMyFileStruct; Nun musst du dich aber darum kümmern, dass die Länge der Zeichenkette in die Datei geschrieben wird und dann entsprechend die Zeichen hinten ran. Dies habe ich C++ oben schon versucht zu implementieren. Alternativ: Wenn du sagst, dass Name und Straße niemals mehr als 255 Zeichen lang werden, dann definier eine struct, welche Strings mit einer festen länge enthält (siehe ShortString bzw. string[] in Delphi):
Code:
Dann könntest du sogar ohne weiteres deine originalen Routinen verwenden und direkt mit den read() und write() Methoden die Struktur ein- und auslesen. Damit treten wieder die vorher genannten Einschränkung in Kraft (Zeichenkettenlänge), aber es würde funktionieren.
struct info
{ char Name[256]; char Strasse[256]; }; Tutorials kann ich dir keine nennen. Ich kann keine Schreiben, da ich schlecht erklären kann und selber habe ich keine gross gelesen, da Auto-Didakt. |
Re: [C++] Binärdateien
@ muetze1,
danke für deine bemühungen. jetzt hab ich s geblickt! __________________________________________________ ______ Das problem ist eingentlich, dass ich einen TFont in einer datei speichern möchte. Da der Tfont record aber auch ansistings enthält hat sich das wohl erledigt. |
Re: [C++] Binärdateien
Zitat:
1. Welcher TFont Record? 2. Wenn es ein WinAPI Record ist - hat er wirklich einen AnsiString? Das wage ich zu bezweifeln. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 10:24 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz