Korrektes Schreiben in eine Datei und Lesen aus einer Datei



  • Guten Tag, prinzipiell bin ich ja mit filestreams vertraut, aber um die Fehler habe ich mich noch nicht so wirklich gekümmert. Wie schreibe ich richtig in eine Datei, wie lese ich richtig?

    Hier mal ein Beispiel, wie ich das Schreiben machen würde:

    std::ofstream os("bla.blubb");
    
    while(os << some_stuff);
    
    if(!os.good())
        // Schreibfehler
    
    os << std::flush;
    
    if(!os.good())
        // Schreibfehler
    

    Und hier mal das Lesen:

    std::ifstream is("bla.blubb");
    
    while(is >> somevar);
    
    if(!is.good())
      // Lesefehler
    

    Ist das so korrekt? Gibt es einfachere Varianten?



  • Wenn du dir den Fehler nicht ausgeben lassen willst, dann kannst du das auch so schreiben, weil der Block der while -Schleife im Moment leer ist (ist vieleicht eine Geschmackssache):

    do 
    {
        os << some_stuff
    } 
    while(os.good());
    


  • Geht darum, dass ich über alle Fehler benachrichtigt werden möchte 😉


  • Mod

    314159265358979 schrieb:

    Geht darum, dass ich über alle Fehler benachrichtigt werden möchte 😉

    Du kannst dir auch exceptions werfen lassen. Dann brauchst du den normalen Code nicht so verunstalten, sondern kannst die Fehlerbehandlung auslagern:
    http://www.cplusplus.com/reference/iostream/ios/exceptions/



  • Ich steh nicht so auf Exceptions, die wirken auf mich irgendwie Performancetechnisch mies - kann aber auch sein dass ich da gerade Blödsinn rede - ich weiß es nicht.



  • 314159265358979 schrieb:

    ...kann aber auch sein dass ich da gerade Blödsinn rede...

    Ja, tust Du ;). Gerade bei Streams dürfte sich die minimale Overhead den Exception vermeintlich mit sich bringen nicht ins Gewicht fallen. Mal ganz davon abgesehen kostet die manuelle Fehlerbahndlung auch...



  • Nur ein Hinweis: !is.good() trifft auch auf das Dateiende zu. Wenn du das von Eingabefehlern unterscheiden willst, solltest du is.bad() verwenden.



  • 314159265358979 schrieb:

    Ich steh nicht so auf Exceptions, die wirken auf mich irgendwie Performancetechnisch mies - kann aber auch sein dass ich da gerade Blödsinn rede - ich weiß es nicht.

    Exceptions selbst bringen bei einem guten Compiler (g++) keinen Overhead mit sich, das Werfen im Stream IMHO auch nicht (irgendwo muss ja getestet werden).

    Was hingegen performancetechnisch mies ist, ist der C++-Stream. Wenn du auf Geschwindigkeit aus bist, musst du dir einen FILE*-Wrapper basteln.



  • fDuJ2 schrieb:

    314159265358979 schrieb:

    Ich steh nicht so auf Exceptions, die wirken auf mich irgendwie Performancetechnisch mies - kann aber auch sein dass ich da gerade Blödsinn rede - ich weiß es nicht.

    Exceptions selbst bringen bei einem guten Compiler (g++) keinen Overhead mit sich, das Werfen im Stream IMHO auch nicht (irgendwo muss ja getestet werden).

    Was hingegen performancetechnisch mies ist, ist der C++-Stream. Wenn du auf Geschwindigkeit aus bist, musst du dir einen FILE*-Wrapper basteln.

    Warum sollten die C++-Streams performancetechnisch mies sein? Das kann ich nicht bestätigen.

    Bei einem SJLJ-Compiler (üblicher) bringen AFAIK sowohl ein try{}-Block als auch das Werfen einen kleinen Overhead mit sich, welcher den einer ständigen Abfrage allerdings kaum übersteigen sollte. Ein Dwarf2-Compiler hat dagegen bei try{}-Blöcken keinen Overhead, ist allerdings auch nicht auf allen Systemen verfügbar. Beide Versionen sind etwa beim TDM-GCC verfügbar.



  • CStoll schrieb:

    solltest du is.bad() verwenden.

    Bei einem fail() wird doch bad() nicht gesetzt, oder?



  • EOutOfResources schrieb:

    CStoll schrieb:

    solltest du is.bad() verwenden.

    Bei einem fail() wird doch bad() nicht gesetzt, oder?

    Punkt für dich, mein Fehler (meine C++ Zeit ist doch schon zu lange her, um mir alle Details zu merken).



  • 314159265358979 schrieb:

    Wie schreibe ich richtig in eine Datei, wie lese ich richtig?

    Du schreibst richtig, indem Du ganz normal einfach schreibst und am Ende das fail-Bit abfragst. Also mit

    ofstream out("bla.blubb");
        out << ...; // alles mögliche
        if( !out ) { // ist identisch mit: if( out.fail() ) {
            cerr << "Fehler beim Schreiben" << endl;
    

    tritt kein Fehler auf, so kannst Du sicher sein, dass alle Daten im unterliegenden streambuf angekommen sind. Sicherer wäre es, vor der Prüfung noch einen sync aufzurufen :

    ofstream out("bla.blubb");
        out << ...; // alles mögliche
        if( !(out << std::flush) ) {
            cerr << "Fehler beim Schreiben" << endl;
    

    Der sync soll die Zeichen, die evt. noch im streambuf gespeichert sind, in das Device schreiben. Mehr kannst Du nicht machen, auch ein close macht meines Wissens nicht mehr.

    Beim Lesen ist es genauso - Lesen und anschließend auf fail-Bit prüfen. Ist es nicht gesetzt, sollten alles bis dahin korrekt gelesen sein.

    ifstream in("bla.blubb");
        in >> ... ; // alles lesen
        if( !in ) {
            cerr << "Fehler beim Lesen" << endl;
    

    im Unterschied zum Schreiben, kann es beim Lesen vorkommen, dass das EOF-Bit gesetzt ist, aber das Fail-Bit nicht - am Ende der Datei. Deshalb wäre ein

    if( !in.good() ) {
    

    nach dem Lesen schlicht ein Fehler.

    Das Fail-Bit wird immer gesetzt, egal welcher Art der aufgetretene Fehler ist. Das Fail-Bit wird i.A. von den Extratoren gesetzt, wenn z.B. ein Formatfehler auftritt. Das Bad-Bit wird gesetzt, wenn der Streambuf eine Exception wirft. Der Stream fängt sie (wenn nicht anders eingestellt) und setzt das Bad-Bit. stream.fail() liefert in jedem Fall 'true'.

    Es versteht sich von selbst, dass zuerst gelesen wird und dann das Fail-Bit geprüft wird - und nicht wie durchaus üblich umgekehrt. .. noch ein Beispiel.

    Gruß
    Werner



  • Vielen Dank, habe meinen Thread etwas aus den Augen verloren. 🙂


Log in to reply