Probleme mit Streams und Dateien
-
Hi Leute
da ich diverse structs in einer Datei speichern (und auch wieder lesen) möchte habe ich mich am C++ FAQ "Streams und Dateien" orientiert.
Problem: die Ausgaben enthalten Seitenweise "Müll". Einige "PATH = ..." Einträge von Windows, "PROMPT" und auch das komplette Alphabet in Klein-und Großbuchstaben.
Hier mal das Struct um das sich alles dreht:
struct Tprocedure { string Source; string Destination; time_t Last; };Angaben zum Projekt:
die Variable "list" enthält diverse Objekte einer Klasse "BACKUP". Diese Klasse enthält auch das struct "Tprocedure", also die eigentlichen Daten die gespeichert werden sollen.
vector <BACKUP*> list;alle Inhalte des zwecks Speichern zuürckgelieferten Objekts wurden untersucht und sind inhaltlich in Ordnung.
Tprocedure proc = list[i]->GetProcedure(j);Hier mal die Funktion die die structs speichert:
void BACKUPLIST::SaveToFile(string filename) { fstream File(filename.c_str(), ios::out|ios::binary); if (File.is_open()) { for (int i = 0; i < list.size(); i++) { for (int j = 0; j < list[i]->GetProcNum(); j++) { Tprocedure proc = list[i]->GetProcedure(j); File.write((const char*)&proc, sizeof(Tprocedure)); } } File.close(); } }Hier nun die Funktion die Daten aus der Datei liest und diese ausgibt:
void BACKUPLIST::LoadFromFile(string filename) { fstream File(filename.c_str(), ios::in|ios::binary); if (File.is_open()) { Tprocedure proc; while (File.read((char*)&proc, sizeof(Tprocedure))) cout << proc.Source << endl; File.close(); } }Der Aufruf der Funktionen LoadFromFile und SaveToFile wird jeweils folgendermaßen durchgeführt:
filesave.LoadFromFile("D:\\Programme\\BackUp_Builder\\data.dat");Mit doppelten Backslashes, also auch korrekt wie ich vermute.
Woran kann das liegen, dass die gespeicherten Daten nicht korrekt geladen werden, oder falsch gespeichert wurden?
Ich hab mich bei der Entwicklung der Funktionen ziemlich präzise an das FAQ gehalten und an die Angaben zu "C++ I/O" und "Streams" auf www.cppreference.com.
-
Da hilft nur eins!
Nimm Linux.
-
linuxnehmer schrieb:
Da hilft nur eins!
Nimm Linux.da hilft nur eins! Rechner wegsperren.
so wie du das machen willst funktioniert das nur mit pods.
std::string haelt intern nur einen zeiger auf den eigendlichen string und noch paar zusaetzliche werte.
damit das klappt musst Tprocedure serialisieren.beispiel:
struct A { std::string s1, s2; } void serialize_string(std::ostream &out, const std::string &s) { std::size_t len = s.size(); out.write(&len, sizeof(len)); out.write(s.c_str(), len); } std::ostream& operator<<(std::ostream &out, const A &a) { serialize_string(out, a.s1); serialize_string(out, a.s2); return out; } void deserialize_string(std::istream &in, std::string &s) { std::size_t len = 0; std::streambuf *buf = in.rdbuf(); in.read(&len, sizeof(len)); for(std::size_t i = 0;i < len;++i) s.assign(buf->sbumpc()); } std::istream& operator>>(std::istream &in, A &a) { deserialize_string(in, a.s1); deserialize_string(in, a.s2); return in; } // so kannst du dann A-objekte in dateien schreiben und wieder auslesen std::ofstream odatei(...); A a; ... odatei << a; ... std::ifstream idatei(...); A a; ... idatei >> a;so koennte es zum beispiel aussehen. hab das nur mal aus dem kopf geschrieben. koennen fehler vorhanden sein.
Meep Meep
-
danke dir für deine Mühe

Ich hatte mir schon gedacht dass es irgendwas mit den Strings zu tun hat.
Ich werd mir das gleich mal anschauen.Gehe ich recht in der Annahme, dass es auf meine Weise funktionieren würde, wenn ich statt der Strings einfach Variablen vom Typ Char[N] benutzen würde, also Character mit definierter Länge?
-
jups
Meep Meep
-
Meep Meep, sieht gut aus, nur
for(std::size_t i = 0;i < len;++i) s.assign(buf->sbumpc());ergibt keinen Sinn.
Wenn man davon ausgeht, daß der String-Speicher intern am Stück vorliegt, dann reicht auch:
s.resize(len); in.read(&s[0], len);Ich weiß, daß camper jetzt wieder meckern wird, aber ich kenne keine Implementation, die das anders macht.
Ansonsten könnte man selbst noch in einer Schleife die Werte einzeln zuweisen:s.resize(len); for(std::size_t i = 0;i < len;++i) s[i] = static_cast<char>(buf->sbumpc());Wahrscheinlich meinte dies Meep Meep so, denn assign überschreibt ja immer wieder den Stringpuffer. (Überleg... ich hab's jetzt: Meep Meep meinte 'append' !!!)
-
~deserialize schrieb:
Ich weiß, daß camper jetzt wieder meckern wird, aber ich kenne keine Implementation, die das anders macht.
Wie richtig gesagt wurde, ist das mit jeder praktisch relevanten Implementation möglich. Zudem wurden entsprechende Garantien in den gegenwärtigen Entwurf des nächsten Standards aufgenommen, man kann also davon ausgehen, das das auch in Zukunft und dann ganz offiziell so möglich ist. Insofern sehe ich keine ernsthaften Probleme.