[gelöst]Seltsames Verhalten von ifstream beim lesen+schreiben
-
Hallo Welt,
heute ist mir folgendes Aufgefallen und ich wollte mal Fragen, ob das normal ist, oder ich etwas nicht bedacht habe. Folgendes Beispiel:
#include <iostream> #include <fstream> using namespace std; /* test.dat sieht so aus: \x00\x01\x02\x03\x04 */ int main() { fstream fhandle("test.dat", fstream::in | fstream::out | fstream::binary); // Ich möchte nun aus dem Byte nach \x02 ein \x00 machen (also aus dem \x03) // Ich weiß, dass \x02 das dritte Byte ist - ergo kann ich hinseeken fhandle.seekp(2, ios_base::beg); // sicher bin ich mir aber nicht, lieber nachgucken... // TEIL A char tmp; fhandle.get(tmp); if(tmp!='\x02') { cout << "Die Datei ist beschädigt!!!" << endl; return 1; } // ENDE TEIL A // TEIL B // Ok, also jetzt das updaten: fhandle.write("\x00", 1); if(fhandle.bad()) { cout << "Und das ist der Beweis für den Fatalen I/O-Error!!!" << endl; // Aber warum??? } // ENDE TEIL B // Und zumachen... fhandle.close(); return 0; }Das Programm funktioniert nicht, da es einen Schreibfehler gibt.
Das Spannende: Wenn man TeilA weglässt funktionierts.
Noch spannender: Wenn man zwischen TeilA und TeilB ein einfachesfhandle.tellg();setzt klappts auch.
Weißt jemand, wie das zu stande kommt?
Edit: Sorry dass das jetzt in AnsiC gelandet ist. Ist natürlich C++.
-
Dieser Thread wurde von Moderator/in Nobuo T aus dem Forum ANSI C in das Forum C++ verschoben.
Im Zweifelsfall bitte auch folgende Hinweise beachten:
C/C++ Forum :: FAQ - Sonstiges :: Wohin mit meiner Frage?Dieses Posting wurde automatisch erzeugt.
-
Also mein Debugger hat nichts zurückgewiesen und auch keinen Schreibfehler entdeckt.
Wie sieht die Eingabedatei test.dat genau aus, denn wenn das nur ASCII-Zeichen sein sollen, dann funktioniert tmp!='\x02' natürlich nicht.
Wenn das HEX-Werte sind, dann muss die Eingabedatei ja auch HEX-Werte enthalten, doch das habe ich nicht hinbekommen.
Wenn das Bytes sind, dann musst du mir mal erklären wie man das so in eine Datei reinschreibt
Mit fhandle.write("\x00", 1); schreibst du auf jeden Fall ACSII-Werte, weshalb das irgendwie kein Sinnn ergibt, da du ja Byte-Werte haben willst...
Habe ich deinen Quelltext richtig verstanden?
-
mhh, seltsam.
Liegts am compiler?Mein gcc 4.3.3 hat damit eindeutig probleme...
-
Vielleicht könntest du ja mal deine Fehler-Anzeige hier posten...
(das was debugger halt schreibt ; mit Zeilenangaben hoffe ich doch
-
Parser schrieb:
Wie sieht die Eingabedatei test.dat genau aus?
Nur ein Beispiel um das Problem zu veranschaulichen - binär: du kannst sie dir bauen mit:
... ofstream fhandle("test.dat", ios::out | ios::binary); fhandle.write("\x00\x01\x02\x03\x04\x05",5); fhandle.close() ...es gibt keine wirkliche Fehlermeldung. Der Schreibbefehl wird nicht ausgeführt stattdessen ereignet sich irgendwo in den tiefen von <fstream> ein fataler I/O-Error.
wie gesagt: ab Zeile 34 ist (fhandle.bad() == true)
-
Bist du dir sicher, dass seekg und good das machen, was du willst?
Ich kenn mich mit den Funktionen speziell jetzt nicht genau aus...
Müssen es unbedingt Streams sein, mit denen du die Datei öffnest, ansonsten hätte ich noch eine andere Variante mit FILE & fopen & fread/fwrite...
-
ähhm... hab mich vertan. Der Fehler ist nicht eof sonder es ist tatsächlich ein Fataler I/O-Error (Das ist mir ja noch nie gelungen ^^). Aber warum???
Update des Quelltextes aus Beitrag 1Übrigens: Der borland C++ Compiler gibt auch die Fehlermeldung aus.
Bist du dir sicher, dass seekg und good das machen, was du willst?
Ja, bin ich.
seekg versetzt den GET-Pointer (der mit dem PUT-Pointer immer identisch ist [siehe http://support.microsoft.com/kb/104634/en-us/]und good() bzw. bad() fragt ab, ob bei dem Schreib-/Lese Zugriff ein Fehler aufgetreten ist.
-
Ich habe noch herausgefunden, dass wenn man write vor bad/good herauskommentiert, dass dann das Ende der Datei noch nicht erreicht ist, also muss der Fehler bei write sein.
Außerdem würde es mit einem ifstream zum Lesen und einem ofstream zum Schreiben funktionieren.
Dann wäre die seek-Funktion seekp(...)
-
Hatten wir vor einiger Zeit schon mal:
Wenn man den selben Stream für Eingabe und Ausgabe benutzt, so muss folgendes beachtet werden:
Eine Ausgabe darf nicht direkt einer Eingabe folgen. Vorher muss entwerder die Ausgabe mit fflush erzwungen werden, oder ein Aufruf einer der Positionierungsfunktionen erfolgen (das hast Du ja auch schon festgestellt).
Soll eine Eingabe auf eine Ausgabe folgen, so muss ebenfalls erst eine der Positionierungsfunktionen aufgerufen werden.
Das steht im C++ Standard, wo ncoh ein Verweis auf den C-Standard enthalten ist, in dem dann das genaue Verhalten beschrieben wird.
-
und schon wieder was dazugelernt, danke
