Binärdatei schreiben
-
Hi @ all,
ich muss einige Werte in eine Binärdatei schreiben.
dazu verwende ich zunächst ofstream:
std::ofstream rd(argv_[1], std::ios::binary | std::ios::ate);
auszugebende Werte:
std::string stringname;
unsigned int x;
char magic[4] = {'x','y','z','\0'};Mit welchen Methoden schreibe ich die verschiedenen Datentypen jetzt
in die Binärdatei?Wenn ich schreieb: rd.put(x) belegt der wert x in der binärdatei nur 2 Byte.
unsigned int braucht doch 4 Byte oder?Wäre super wenn mir hier jemand helfen könnte.
thx
-
file.write(magic, 4); unsigned i; static_assert(sizeof(i) == 4); //nehm ich jetzt mal an file.write(reinterpret_cast<const char *>(&i), sizeof(i)); std::string str; file.write(str.c_str(), str.size());
-
super hat funktioniert. kannst du mir vl noch die zeilen erklären?
was macht
static_assert(sizeof(i) == 4)
und
file.write(reinterpret_cast<const char *>(&i), sizeof(i));
genau? wieso muss ich hier ein reinterpret_cast machen?
thx
-
static_assert() funktioniert so ähnlich wie assert(), wird allerdings schon beim Compilieren ausgewertet. Damit liefert der Compiler einen Fehler, wenn die Größe eines "unsigned int" nicht gleich 4 ist.
Der reinterpret_cast interpretiert den übergebenen Wert neu - in dem Fall übergibst du einen Zeiger auf unsigned und verwendest ihn, als wäre er ein Zeiger auf char. Sowas macht man nur, wenn man weiß was man tut - ich bin mir noch nichtmal sicher, ob das hier überhaupt notwendig ist.
-
alles klar. vielen dank für die hilfe

-
CStoll schrieb:
static_assert() funktioniert so ähnlich wie assert(), wird allerdings schon beim Compilieren ausgewertet. Damit liefert der Compiler einen Fehler, wenn die Größe eines "unsigned int" nicht gleich 4 ist.
Der reinterpret_cast interpretiert den übergebenen Wert neu - in dem Fall übergibst du einen Zeiger auf unsigned und verwendest ihn, als wäre er ein Zeiger auf char. Sowas macht man nur, wenn man weiß was man tut - ich bin mir noch nichtmal sicher, ob das hier überhaupt notwendig ist.
Theoretisch wäre ein static_cast auf const void* und dann ein static_cast auf const char* am besten.

-
Ethon_ schrieb:
Theoretisch wäre ein static_cast auf const void* und dann ein static_cast auf const char* am besten.

Warum am besten? Genau dafür gibt es doch
reinterpret_cast. Der vermeidet sowohl den Umweg übervoid *, als auch den unscheinbaren C-Cast.Natürlich sollte man beachten, dass
unsignedwie die meisten Typen nicht auf allen Plattformen gleich groß ist. Es scheint so harmlos, sich auf die Größe von Typen zu verlassen. "Immer diese Frickler mit ihren exotischen Plattformen und den komischen Datentypen." Ein Beispiel aus der Praxis zeigt aber, dass das ein Trugschluss ist:time_twar bei Visual C++ 7 noch 32 bit groß, einige Versionen später hat Microsoft den Typ auf 64 bit vergrößert. Wenn dieser Typ in einem Binärprotokoll verwendet wurde, konnten schwer zu findende Bugs entstehen. Das weiß ich aus eigener Erfahrung (nein, ich habe den Code nicht geschrieben, sondern nur korrigiert). Niemand garantiert, dass andere Typen immer gleich groß sein werden. Also sollte man sich von Anfang an angewöhnen,typedefs zu verwenden. Am besten ausboost/cstdint.hpp.
-
TyRoXx schrieb:
Ethon_ schrieb:
Theoretisch wäre ein static_cast auf const void* und dann ein static_cast auf const char* am besten.

Warum am besten? Genau dafür gibt es doch
reinterpret_cast. Der vermeidet sowohl den Umweg übervoid *, als auch den unscheinbaren C-Cast.Es wäre am Sichersten, dafür ist es mehr Schreibarbeit.
Ein reinterpret_cast kann alles zu einem const char* verwursten, per static_cast nur pointer.Hätte er zb vergessen sein int i zu referenzieren, hätte der Compiler das mit einem reinterpreted_cast ohne Meckern geschluckt.
-
Ethon_ schrieb:
Es wäre am Sichersten, dafür ist es mehr Schreibarbeit.
Ein reinterpret_cast kann alles zu einem const char* verwursten, per static_cast nur pointer.Hätte er zb vergessen sein int i zu referenzieren, hätte der Compiler das mit einem reinterpreted_cast ohne Meckern geschluckt.
Ja, das ist ein Argument. Vielleicht sollte man sich eine Template-Funktion
pointer_castoder so bauen, welche die Typen prüft.