fwrite - ab 284 Byte gibt`s eines Gratis dazu ???
-
Hallo zusammen,
ich habe ein recht merkwürdiges - und mich in den Wahnsinn treibendes - verhalten bei der Funktion fwrite.
Es ist folgendermaßen:
Ich habe ein HWND Array, was folgendermaßen deklariert wurde:
HWND hwndAr[78];
In diesem Array stehen verschiedene Window-Handles drin. Wie dem auch sei, lasse ich diese folgendermaßen in eine Datei schreiben:
FILE* SaveFile; fopen_s( &SaveFile, "bla", "w+" ); fwrite( &hwndAr, 78 * sizeof(HWND), 1, SaveFile ); fclose( SaveFile );
Jetzt wunderte mich schon, dass die Datei nicht 312 ( wie es nach 78 * 4 ergeben müsste ), sondern 313 Byte groß ist.
Als ich das Ganze dann folgendermaßen eingelesen hatte:
HWND hwndAr[78]; fread_s( &hwndAr, 78 * sizeof(HWND), 78 * sizeof(HWND), 1, myFile ); for( int i = 0; i < 78; i++ ) { std::cout << i << "\t" << *(hwndAr + i)/*hwndAr[i]*/ << std::endl; }
... bemerkte ich, dass alle Werte bis auf die letzten 5 (?!) korrekt eingelesen wurden.
Also bemühte ich einen Hex-Editor um zu überprüfen, was denn genau in der Datei steht, um den Fehler zunächst beim Schreiben zu suchen.
Dabei stellte ich fest, dass zwischen dem 71. und dem 72. Eintrag (welche beide korrekt sind) ein weiteres Byte geschrieben wurde, welches dort nicht stehen dürfte.
Ich hoffe, dass mir jemand weiterhelfen kann, denn auch wenn ich jeden Wert des Arrays einzeln rausschreibe, habe ich ab dem 72. Eintrag meines HWNDs dieses "Extra-Byte" ...
-
"w+b"
-
1. Was hat das mit C++ zu tun? fwrite ist eine C Funktion! Dein ganzer Code ist C und WinAPI. Wie kommst du auf die Idee, dass dies etwas mit C++ zu tun hat? *mal die Frage stellen will*
2. Wie MFK gesagt hat, wenn du willst, dass die Daten 1:1 rausgehen, dann nutze das"b"
. Wenn es nicht gesetzt ist, wird angenommen, dass du ein Textfile beschreiben willst, wodurch gewisse Änderungen automatisch vorgenommen werden. Zum Beispiel wird auf Windows aus einem\n
ein\r\n
.
Ist zwar eine C++ Referenz, aber stimmt trotzdem als Lektüre:
http://www.cplusplus.com/reference/clibrary/cstdio/fopen.htmlGrüssli
-
Das 313. Zeichen müsste EOF sein, also ganz normal, dass die Datei 1 Byte größer ist.
-
Dravere schrieb:
1. Was hat das mit C++ zu tun?
Na aber da steht doch cout!
-
_matze schrieb:
Dravere schrieb:
1. Was hat das mit C++ zu tun?
Na aber da steht doch cout!
Oha, unter all dem C Code ganz übersehen. Und sogar einstd::endl
dahinter. Ich glaube aber, dass ich meine Frage trotzdem so stehen lassen kann. Vor allem, da sich die Frage umfwrite
/fopen
und co dreht, was wirklich nichts mit C++ zu tun hat. Sogar wenn man in C++ programmiert, würde ich mit so eine Frage ins C Forum. Kommt schliesslich von denen :pGrüssli
-
Ich glaube, wenn ich jetzt anfangen würde von wegen "die Funktionen sind doch Bestandteil von C++...", dann würdest du entgültig auf die Palme gehen, was?
Nee, hast schon Recht...
-
feigling schrieb:
Das 313. Zeichen müsste EOF sein, also ganz normal, dass die Datei 1 Byte größer ist.
Es gibt kein Zeichen "EOF". Leere Dateien sind auch nicht 1 Byte groß.
-
feigling schrieb:
Das 313. Zeichen müsste EOF sein
Huh? EOF-Zeichen am Ende von Dateien gibt's nicht.
-
Dravere schrieb:
1. Was hat das mit C++ zu tun? fwrite ist eine C Funktion! Dein ganzer Code ist C und WinAPI. Wie kommst du auf die Idee, dass dies etwas mit C++ zu tun hat? *mal die Frage stellen will*
2. Wie MFK gesagt hat, wenn du willst, dass die Daten 1:1 rausgehen, dann nutze das"b"
. Wenn es nicht gesetzt ist, wird angenommen, dass du ein Textfile beschreiben willst, wodurch gewisse Änderungen automatisch vorgenommen werden. Zum Beispiel wird auf Windows aus einem\n
ein\r\n
.
Ist zwar eine C++ Referenz, aber stimmt trotzdem als Lektüre:
http://www.cplusplus.com/reference/clibrary/cstdio/fopen.htmlGrüssli
Und was genau ist unter der Referenz nun mehr C++ als mein Code? Steht doch genau so auch dort drin.
Also liegt mein Problem darin, dass ich "w+b" schreiben muss. Ich gehe davon aus, dass das "b" für binary steht, aber kann mir mal jemand sagen, woher man das wissen soll, wenn das nirgendwo - auch nicht in der Visual Studio Hilfe - erwähnt wird?
-
FrEEzE2046 schrieb:
kann mir mal jemand sagen, woher man das wissen soll, wenn das nirgendwo - auch nicht in der Visual Studio Hilfe - erwähnt wird?
Also in der MSDN (fopen) steht es drin:
MSDN schrieb:
Also, in text mode, carriage return–linefeed combinations are translated into single linefeeds on input, and linefeed characters are translated to carriage return–linefeed combinations on output [...]
b Open in binary (untranslated) mode; translations involving carriage-return and linefeed characters are suppressed.
-
FrEEzE2046 schrieb:
Und was genau ist unter der Referenz nun mehr C++ als mein Code? Steht doch genau so auch dort drin.
Ich habe nie gesagt, dass die verlinkte Referenz mehr C++ Code aufzeigt als deiner.
Die Sache ist, du nutzt C Funktionen. Die sind zwar über<cstdio>
auch in C++ nutzbar, doch normalerweise nutzt man in C++ die IO Streamklassen, weil diese zahlreiche Vorteile gegenüber den C Funktionen haben. Sofern man C++ programmiert.FrEEzE2046 schrieb:
Also liegt mein Problem darin, dass ich "w+b" schreiben muss. Ich gehe davon aus, dass das "b" für binary steht, ...
Zu beidem, ja.
FrEEzE2046 schrieb:
aber kann mir mal jemand sagen, woher man das wissen soll, wenn das nirgendwo - auch nicht in der Visual Studio Hilfe - erwähnt wird?
Durch ein gutes Buch?
Durch eine gute Referenz?
In dem man die MSDN richtig liest:
http://msdn.microsoft.com/en-us/library/yeby3zcb.aspx
(steht da auch drin, somit auch in der VS Hilfe)Grüssli
-
Badestrand schrieb:
feigling schrieb:
Das 313. Zeichen müsste EOF sein
Huh? EOF-Zeichen am Ende von Dateien gibt's nicht.
Oha, echt? :o Dann verwechse ich das mit irgendwas anderem. Ka, wie ich dann drauf komme, dass es bei Dateien noch ein Abschlusstoken gibt. Sorry.
-
mmmh, dass hab ich echt nicht gelesen. Ich habe den Fehler aber auch eher bei fwrite gesucht.
Wie könnte ich mir denn am besten mit C++ - Funktionen die Daten speichern?
-
feigling schrieb:
Badestrand schrieb:
feigling schrieb:
Das 313. Zeichen müsste EOF sein
Huh? EOF-Zeichen am Ende von Dateien gibt's nicht.
Oha, echt? :o Dann verwechse ich das mit irgendwas anderem. Ka, wie ich dann drauf komme, dass es bei Dateien noch ein Abschlusstoken gibt. Sorry.
Lass dich von denen nicht verwirren. Es gibt EOF Zeichen:
http://de.wikipedia.org/wiki/End_of_FileAllerdings werden die meistens nicht reingeschrieben. Das Problem mit dem EOF Zeichen hat man eher beim Lesen von binären Daten. Beim Schreiben wird zwar kein EOF Zeichen erzeugt, beim Lesen aber durchaus erkannt.
@FrEEzE2046,
http://magazin.c-plusplus.net/artikel/Ein- und Ausgabe in CPlusPlus - IO-StreamsIst zwar jetzt mehr auf Text bezogen. Aber ansonsten halt die Referenz zu den Filestreams in C++:
http://www.cplusplus.com/reference/iostream/ifstream/
http://www.cplusplus.com/reference/iostream/ofstream/
http://www.cplusplus.com/reference/iostream/fstream/Am besten lernst du darüber, wenn du ein gutes C++ Buch liest.
Grüssli
-
Dravere schrieb:
Ich habe nie gesagt, dass die verlinkte Referenz mehr C++ Code aufzeigt als deiner.
Die Sache ist, du nutzt C Funktionen. Die sind zwar über<cstdio>
auch in C++ nutzbar, doch normalerweise nutzt man in C++ die IO Streamklassen, weil diese zahlreiche Vorteile gegenüber den C Funktionen haben. Sofern man C++ programmiert.Also ich benutze auch fats ausschließlich fopen und fread/fwrite, den Vorteil in fstreams gegenüber der C Variante hab ich bisher nicht gesehen, sogar eher Nachteile weil die C Version void* annimt wärend fstream unbedingt char* will.
-
Dravere schrieb:
feigling schrieb:
Badestrand schrieb:
feigling schrieb:
Das 313. Zeichen müsste EOF sein
Huh? EOF-Zeichen am Ende von Dateien gibt's nicht.
Oha, echt? :o Dann verwechse ich das mit irgendwas anderem. Ka, wie ich dann drauf komme, dass es bei Dateien noch ein Abschlusstoken gibt. Sorry.
Lass dich von denen nicht verwirren. Es gibt EOF Zeichen:
http://de.wikipedia.org/wiki/End_of_FileAllerdings werden die meistens nicht reingeschrieben. Das Problem mit dem EOF Zeichen hat man eher beim Lesen von binären Daten. Beim Schreiben wird zwar kein EOF Zeichen erzeugt, beim Lesen aber durchaus erkannt.
Dass es EOF gibt, ist klar. Ich hatte aber auch irgendwie im Kopf, dass EOF auch in die Datei geschrieben wird, zumindest wenn man nicht im Binärmodus schreibt.
Edit:
Wiki schrieb:
Historisch fügte Microsoft DOS das ASCII-Steuerzeichen SUB 0x1A (eben Strg-Z) tatsächlich an das Ende einer Datei. Die Kompatibilität zu älteren Systemen (z. B. CP/M) wäre sonst nicht zu gewährleisten gewesen.
Ok, da stehts doch, dass es zumindest früher auch geschrieben wurde.
-
mmmh,
wird nicht vielmehr die aktuelle Position in der Datei mit der letzten Position verglichen und somit das Dateiende erkannt?
-
Xebov schrieb:
Also ich benutze auch fats ausschließlich fopen und fread/fwrite, den Vorteil in fstreams gegenüber der C Variante hab ich bisher nicht gesehen, sogar eher Nachteile weil die C Version void* annimt wärend fstream unbedingt char* will.
Und da habe ich schon Leute gesehen, welche dann das hier machen:
class Derived : public Base { // Ein paar virtuelle Funktionen. }; // ... Derived d; fwrite(d, sizeof(d), 1, file);
Funktioniert ja, weil es kompiliert. Bei einem
char*
kommen sie immerhin angelaufen und fragen nach, wie man den Typen in einenchar*
umwandelt. Ist wie bei Exceptions, man kann eincatch
machen und die Neulinge davor bewahren schlimmes zu machenDer
char*
führt einem dann auch noch dazu zu überlegen, wie die Daten nun geschrieben werden. BE? LE?
Wenn man dann entsprechend die Sache anpassen will, nützt auch dasvoid*
vonfwrite
nichts mehr, da man jedes Byte in der richtigen Reihenfolge reinbekommen muss.Ansonsten bieten die Streams halt mehr Möglichkeiten. Vor allem durch die gemeinsamen Basisklassen. So kann man einfach einen
std::basic_istream
erwarten, wohin dann tatsächlich geschrieben wir, kann man dem Nutzer freilassen. Er kann so die Sache in einen Puffer umleiten oder auch gleich irgendwo anders hinschicken.
Auch bekommt man über die Streams gleich Exceptions, welche man zwar immer manuell selber setzen muss, also dass sie geworfen werden sollen, aber immerhin.
http://www.cplusplus.com/reference/iostream/ios/exceptions.htmlWerner Salomon hat glaube ich hier irgendwo auch mal eine Streamklasse gezeigt, welche etwas angenehmer zu handhaben ist für das binäre Lesen und Schreiben.
Grüssli
-
Dravere schrieb:
Funktioniert ja, weil es kompiliert. Bei einem
char*
kommen sie immerhin angelaufen und fragen nach, wie man den Typen in einenchar*
umwandelt. Ist wie bei Exceptions, man kann eincatch
machen und die Neulinge davor bewahren schlimmes zu machenJa gut ok, aber ich denke wer sowas einsetzt solte schon wissen was er da tut, es gibt zu dem Thema ja imerhin genug Dokumentation das sowas nicht passieren sollte.