AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

[C++] Binärdateien

Ein Thema von Mark90 · begonnen am 30. Okt 2007 · letzter Beitrag vom 31. Okt 2007
Antwort Antwort
Seite 1 von 2  1 2      
Mark90
(Gast)

n/a Beiträge
 
#1

[C++] Binärdateien

  Alt 30. Okt 2007, 20:11
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:
struct info
{
   AnsiString Name;
   AnsiString Strasse;
};
meine lesen button
Code:
        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;
mein schreiben button

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();
  Mit Zitat antworten Zitat
Muetze1
(Gast)

n/a Beiträge
 
#2

Re: [C++] Binärdateien

  Alt 30. Okt 2007, 20:32
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.
  Mit Zitat antworten Zitat
Mark90
(Gast)

n/a Beiträge
 
#3

Re: [C++] Binärdateien

  Alt 30. Okt 2007, 20:41
Zitat von Muetze1:
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.
versteh ich irgendwie nicht
  Mit Zitat antworten Zitat
mkinzler
(Moderator)

Registriert seit: 9. Dez 2005
Ort: Heilbronn
39.858 Beiträge
 
Delphi 11 Alexandria
 
#4

Re: [C++] Binärdateien

  Alt 30. Okt 2007, 20:44
Du speicherst die Speicheradresse, an dem der String zum Speicherzeitpunkt steht in die Datei ab, nicht den Inhalt der Zeichenkette.
Markus Kinzler
  Mit Zitat antworten Zitat
Mark90
(Gast)

n/a Beiträge
 
#5

Re: [C++] Binärdateien

  Alt 30. Okt 2007, 22:33
Wie könnte ich, dieses Problem umgehen?

vielleicht so, oder

*AnsiString dereferzierung auf ansistring
  Mit Zitat antworten Zitat
Muetze1
(Gast)

n/a Beiträge
 
#6

Re: [C++] Binärdateien

  Alt 30. Okt 2007, 22:46
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:
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?
@other: könntet ihr euch mal den Kommentar anschauen??

/EDIT: andere Lösung

Code:
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;
Alles ungetester Code, so hier hingeschrieben
  Mit Zitat antworten Zitat
Mark90
(Gast)

n/a Beiträge
 
#7

Re: [C++] Binärdateien

  Alt 31. Okt 2007, 07:46
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?
  Mit Zitat antworten Zitat
Muetze1
(Gast)

n/a Beiträge
 
#8

Re: [C++] Binärdateien

  Alt 31. Okt 2007, 14:40
Zitat von Mark90:
in delphi hatte ich für das speichern von records typisierte dateien verwendet. -> typisierte dateien sind ja nicht das gleiche wie binäre dateien?
Jain, doch, irgendwie sind sie schon recht ähnlich. Aber der Reihe nach.

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:
type
  TMyFileStruct = Record
    name: string;
    strasse: string;
  end;

var
  MyFile: file of TMyFileStruct;
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).

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:
type
  TMyFileStruct = Record
    name: shortstring; // bzw. string[x]
    strasse: shortstring;
  end;

var
  MyFile: file of TMyFileStruct;
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).

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:
struct info
{
   char Name[256];
   char Strasse[256];
};
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.

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.
  Mit Zitat antworten Zitat
Mark90
(Gast)

n/a Beiträge
 
#9

Re: [C++] Binärdateien

  Alt 31. Okt 2007, 15:21
@ 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.
  Mit Zitat antworten Zitat
Muetze1
(Gast)

n/a Beiträge
 
#10

Re: [C++] Binärdateien

  Alt 31. Okt 2007, 16:00
Zitat von Mark90:
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.
Habe jetzt erst gesehen, dass dies keine Signatur ist. Frage:

1. Welcher TFont Record?
2. Wenn es ein WinAPI Record ist - hat er wirklich einen AnsiString? Das wage ich zu bezweifeln.
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 2  1 2      


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 04:54 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz