Probleme beim auslesen einer Textdatei
-
Hallo
Ich lese eine Textdatei mit folgender Funktion aus:
// loads fragments from file: bool Assembler::load (const std::string& filename) { std::string tmp_string; std::ifstream inputFile (filename.c_str()); // Error if file coud not be opened: if (inputFile.fail()) std::cerr << "Konnte die Datei \"" << filename << "\" nicht oeffnen." << std::endl; // read file: while (!inputFile.eof() && !inputFile.fail()) { getline (inputFile, tmp_string); fragments_.push_back(tmp_string); } // operation successful?: return !inputFile.fail(); }Das funktioniert ganz gut. Das Problem ist jetzt, dass die Funktion false zurückgibt, wenn am Ende noch eine Leerzeile steht. Wie kann ich das abfangen (das Auslesen war dann ja erfolgreich)?
Vielen Dank
- Egg
-
Also zu lesen bis eof() true zurück gibt ist nicht gerade eine gute idee. Da das eof dann mitgelesen wird. Und der stream dann bei fail() immer true zurückgibt.
Versuche es einfach mal so:
// loads fragments from file: bool Assembler::load (const std::string& filename) { std::string tmp_string; std::ifstream inputFile (filename.c_str()); // Error if file coud not be opened: if (!inputFile) { std::cerr << "Konnte die Datei \"" << filename << "\" nicht oeffnen." << std::endl; return false; } // read file: while (getline (inputFile, tmp_string)) fragments_.push_back(tmp_string); // operation successful?: return inputFile.good(); }
-
Die Idee ist gut. Danke!
-
evilissimo schrieb:
// read file: while (getline (inputFile, tmp_string)) fragments_.push_back(tmp_string); // operation successful?: return inputFile.good(); }lt. Standard gibt diese Methode IMMER 'false' zurück. Die Funtion getline liefert den Stream - also 'inputFile' - dieser ist in eine bool-Variable konvertierbar und liefert !fail(). Folglich endet die while-Schleife, wenn der Stream auf fail geht - also z.B. wenn über das Ende hinaus gelesen wird. Ein Stream mit gesetztem fail-Bit ist nie good.
Vorschlag: lese am Ende einer Zeile alle white-space-Character und prüfe dann auf eof-Bit.
do { getline (inputFile, tmp_string); // ... } while( inputFile.good() && !(inputFile >> std::ws).eof() ); return !inputFile.fail();Gruß
Werner
-
Hallo Werner
Bei deiner Variante bricht er aber mit nem Zeilenumbruch am Ende der Datei ab und gibt false zurück...
Grüße
- Egg
-
Egg schrieb:
Bei deiner Variante bricht er aber mit nem Zeilenumbruch am Ende der Datei ab und gibt false zurück...
Funktioniert der Vorschlag von evilissimo bei Dir?
Ich habe es mit dem MS VC6 und MS VC7 ausprobiert. Meine Variante funktioniert in beiden Umgebungen. Ich könnte mir vorstellen, dass der Aufruf von std::ws einen Fehler verursachen könnte, wenn der Lese-Zeiger bereits auf EOF steht, obwohl das eof-Bit noch nicht gesetzt ist.
Welche Umgebung benutzt Du?Gruß
Werner
PS.: muss weg; antworte ggf. später
-
Hi
Ich benutze Cygwin. Folgenden Code benutze ich jetzt der funktioniert.
// loads fragments from file: bool Assembler::load (const std::string& filename) { std::string tmp_string; std::ifstream inputFile (filename.c_str()); // Error if file coud not be opened: if (!inputFile) return false; // read file: while (getline (inputFile, tmp_string)) { // if line is not empty, save fragment: if (tmp_string != "") {fragments_.push_back(tmp_string);} } return true; }Meint ihr das kann man so lassen? Ich meine eine leere Zeile ist ja im Prinzip immer "" wenn keine Leerzeichen drinstehen - und das kann ich ausschließen.
Wenn ich "return false;" mache verlässt er ja die Funktion, nicht?Grüße
- Egg
-
@Werner Salomon
warum nicht einfach:while (getline (inputFile, tmp_string)) { // if line is not empty, save fragment: if (tmp_string != "") {fragments_.push_back(tmp_string);} } return inputFile.eof();Wenn ich am Ende der Schleife bin, dann weiß ich, dass fail() true liefer, also das entweder das fail- oder das bad-bit gesetzt ist. Das kann drei Gründe haben: a) Formatfehler (setzt failbit) b) schwerwiegender I/O-Fehler (setzt badbit) c) Leseversuch wurde wegen End-of-File abgebrochen (setzt failbit nachdem zuvor eofbit gesetzt wurde)
Wenn letzteres gilt, weiß ich, dass vorher nicht ersteres und zweiteres galt. Also kann ich in diesem Fall true liefern, da alle Daten gelesen wurden.
Wurde die Schleife hingen wegen a) oder b) abgebrochen, dann kann c) nicht gelten und ich habe auf jeden Fall nicht die ganze Eingabe verarbeitet.
-
Hallo Hume, Hallo Egg
im Prinzip gebe ich Hume recht. Wenn innerhalb von Stream und darunterliegenden Streambuf alles richtig läuft, sollte Dein Vorschlag funktionieren. Trotzdem würde ich eher zu der Lösung tendieren, die Egg als letztes vorgeschlagen hat.
Das Lesen bis zum 'bitteren' Ende ist in der Praxis nicht immer vom "Lesen bis ein Fehler auftritt" zu unterscheiden. Ich habe selber einige Derivate von Streambuf entwickelt und es werfen nicht alle eine Exception (setzt bad-Bit), wenn das darunterliegende Device einen fatalen Fehler hat. Es werden manchmal einfach keine Zeichen mehr geliefert und das heißt nunmal EOF.BTW: Ich habe es inzwischen auch unter MinGW 3.2.0 ausprobiert. Auch da funktioniert das mit '>> std::ws' wie erwartet.
Gruß
Werner