Ein- und Ausgabe in Datei



  • Hallo an alle :p

    Hab folgendes Problem beim lesen einer Datei. Konkret gesagt kann ich mit dem get(zeichen) befegl eine datei 'abtasten' aber nur einmal obwohl ich mittels der seekg(0, ios::beg) wieder den kursor zum anfang verschiebe. analog dazu geht es wunderbar wenn ich es mittles der read(zeichenkette,zeichenlaenge) funktion erledige. meine frage wäre wie könnte man beim benutzen von get() den kursor zum anfang verschieben um nochmal neu zu lesen. Danke ! 😋

    #include <iostream>
    #include <fstream>
    using namespace std;
    int main(void)
    {
    
    ifstream datei;
    datei.open("testdatei.dat", ios::in|ios::binary);
    
    char zeichen;
    int anzahl=0;
    
    cout << "tellg() am anfang ist " << datei.tellg() << endl;
    cout << "Inhalt Nr.1 : ";
    while(datei.get(zeichen)){cout << zeichen;}
    cout << "\ntellg() nach dem lesen ist " << datei.tellg() << endl;
    datei.seekg(0, ios::beg);
    cout << "tellg() nach dem ruecksetzen ist " << datei.tellg() << endl;
    cout << "Inhalt Nr.2 : ";
    while(datei.get(zeichen)){cout << zeichen;}
    
    datei.close();
    cout << "\n\nEnde mit Eingabetaste...";
    cin.get();
    
    }
    
    #include <iostream>
    #include <fstream>
    using namespace std;
    int main(void)
    {
    
    unsigned int zeichenlaenge=0;
    ifstream datei;
    datei.open("testdatei.dat", ios::in|ios::binary);
    datei.seekg(0,ios::end);
    zeichenlaenge=datei.tellg();
    datei.seekg(0,ios::beg);
    
    char zeichenkette[zeichenlaenge+1];
    
    datei.read(zeichenkette,zeichenlaenge);
    cout << "Inhalt Nr.1 : " << zeichenkette;
    
    datei.seekg(0, ios::beg);
    
    datei.read(zeichenkette,zeichenlaenge);
    cout << "\nInhalt Nr.2 : " << zeichenkette;
    
    datei.close();
    cout << "\n\nEnde mit Eingabetaste...";
    cin.get();
    
    }
    


  • Naja, gehen wir mal durch, was genau passiert:

    while (datei.get(zeichen))
        std::cout << zeichen;
    

    Das sieht ja so ganz nett aus, doch was genau ist die Abbruchbedingung? Richtig! der operator void* von std::ifstream wird NULL zurück geben und damit wird die while-Schleife verlassen.
    (std::ifstream::get gibt Referenz auf sich selbst zurück). Doch wann gibt operator void* NULL zurück? Wenn das Ende der Datei erreicht ist, ein Fehler aufgetreten ist usw. Wenn ein Fehler aufgetreten ist, schlägt aber jedes weitere Einlesen fehl! Du musst ihm erstmal sagen, das du bemerkt hast, das ein Fehler aufgetreten ist, oder das Ende der Datei erreicht ist, und er sich nichtmehr merken muss, dass ein Fehler da war. (std::ifstream::clear).

    #include <iostream>
    #include <fstream>
    
    int main()
    {
        std::ifstream file_stream("testdatei.dat", std::ios_base::binary);
        if (!file_stream) return 1;
    
        std::cout << "Inhalt Nr.1 : " << std::endl;
    
        char tmp_char(0);
        while (file_stream.get(tmp_char)) std::cout << tmp_char;
    
        std::cout << "Die Datei ist " << file_stream.tellg() << " lang!" << std::endl;
    
        file_stream.seekg(0, std::ios::beg);
        file_stream.clear(); // !!!
    
        std::cout << "Inhalt Nr.2 : " << std::endl;
        while (file_stream.get(tmp_char)) std::cout << tmp_char;
    
        std::cout << "\n\nEnde mit Eingabetaste...";
        std::cin.get();
    }
    

    so sollte das gehen. Doch einfacher kansnt du es dir schon machen:

    #include <vector>
    #include <fstream>
    #include <iterator>
    
    int main()
    {
        std::ifstream file_stream("testdata.dat");
        std::vector<char> file_data(std::istream_iterator<char>(file_stream), std::istream_iterator<char>());
        // file_data enthält kompletten Dateiinhalt. file_data.size() ist Anzahl der Zeichen in Datei ...
    }
    

    .



  • Jaaaaa !

    So einfach kan das leben sein 😉

    Wo soll ich jetzt die Hand schüttlen 😋

    Danke, war echt ein scheinbar unlösbares problem. und mit flush wird der dateiinhalt gelöschr, nicht ?

    Der zweite Code übersteigt meine Kentnisse leidergottes, #include <vector>
    #include <iterator>
    was das bitte. 😕

    Noch etwas : ich dachte dass ich mit seekg(0) den kursor automatisch zu 0 setze, warum klappt das bei der read() funktion ? nach meiner recherche 🕶

    while(datei.get(zeichen)|| int a++<10){cout << zeichen;}
    

    bekomme ich trotz des setzens von seekg(0) das letzt zeichen ausgegeben. ⚠



  • Nochmal in Ruhe hinsetzen und neu schreiben. So verstehe ich nichts von dem was du von mir wissen willst 😉



  • ok, tut mir leid, war ufgeregt 🤡

    mich wunderte nur dass wenn ich seekg() auf null setze, seekg(0) oder seekg(0,ios::beg) der kursor zum anfang wandert, aber das lesen klappt dann trotzdem nicht mehr, erst mit clear(). !! obwohl .tellg()=0 ist !! ich will bloss nicht noch weiter an diesem thema rumbohren aber komisch ist es dennoch für micht. warum es bei get() nur mittles clear() geht und bei .write() es reicht den kursor zu verschieben, .seeekg(0, ios::beg) istnoch rätselhaft.

    du sagtest es hängt mit dem rückgabewert zusammen, ok, aber wenn tellg()=0 warum soll das lesen nicht möglich sein... die bedienung while verlangt ja nur dass es etwas zum lesen gibt 😕



  • du sagtest es hängt mit dem rückgabewert zusammen, ok, aber wenn tellg()=0 warum soll das lesen nicht möglich sein... die bedienung while verlangt ja nur dass es etwas zum lesen gibt 😕

    Nein, so ist es genau nicht 😉

    Also, du musst grundlegend zu den Streams in C++ wissen, dass sie sog. Error/Failure-Flags haben(s. std::ios_base::iostate). Wenn diese gesetzt sind, verweigert der Stream seinen Dienst(Lesen / Schreiben), bis diese wieder entfernt wurden. (Das ist eine Möglichkeit dem Programmierer mitzuteilen, dass da was nicht geklappt hat ...).

    Ob nun ein Error (badbit)-, Failure(failbit)-Flag gesetzt ist, oder nicht(goodbit), kannst du mit folgenden Memberfunktionen abfragen:
    - rdstate
    - good (goodbit set?)
    - bad (badbit set?)
    - fail

    Zusätzlich zu diesen Zuständen/Flags, gibt es noch das EndOfFile-Flag (eofbit), das du per eof abfragen kannst. Das Problem bei diesem Flag ist allerdings, das es erst gesetzt ist, wenn das Einlesen bereits einmal nicht geklappt hat/möglich war, d.h. dass das Dateiende erreicht ist.

    Diese Fehlerflags(failbit, badbit, eofbit), kannst du mit clear zurücksetzen. Dann klappt es auch wieder mit dem Lesen!

    Zu den bereits genannten Möglichkeiten, gibt es zum Abfragen der Zustände noch zwei operatoren:
    - operator! ( true wenn Fehlerflag gestetzt)
    - operator void* (NULL wenn Fehlerflag gesetzt)

    In deinem Beispiel:

    while (datei.get(zeichen))
        std::cout << zeichen;
    

    Du nutzt den operator void* (implizite Typumwandlung) der Referenz deines std::ifstream-Objektes, das die get-Funktion zurück gibt (Referenz auf sich selbst, um Arbeit mit Streams zu erleichtern).

    Hoffe es ist einigermaßen verständlich ausgedrückt ... sonst frag nochmal nach!



  • ne jetzt nicht mehr 👍

    hab wieder mal viel neues interesantes erfahren 🕶

    das würde auch erklären warum ich trotz setztens des seekg(0,ios::beg) ich immer noch den letzten buchstaben zu lesen bekamm.

    die zwei biblitheken vector und iterator hab ich mir auch angegukt.
    sind diese zu empfehlen und wenn ja warum ? können alle systheme mit diesen befehlen klar 😕



  • Alles was im Standard ist(also alles was auch im Namensraum std ist), sollte auf jeden System laufen 😉

    Das Iterator-Muster (Iterator Design Pattern bei google.de eingeben) solltest du verwenden, ja.

    std::vector ist sozusagen ein dynamischer Array(new [] / delete []) der sich aber selbst um das aufräumen kümmert und noch ein paar andere Optimierungen beinhaltet ... (vereinfacht gesagt)



  • soo, auch nicht schlecht... , aber bevor ich mich dammit beschäftige werde ich als erstes mal die templates anschauen und dannach die string klasse sonst klappt am ende garnix :p

    mit system meinte ich zb. nen router oder andere geräte die man programieren könnte. 😃 kan man dort auch alle befehle von c++ anwenden oder nur von c, oder was 😋

    noch was, um nicht zu fragen was drinn sei frage ich mal umgekehr, was ist nicht im std namespace drinn abgesehen von irgen welchen privaten klassen etc.

    iostream sollte aber auch drinn sein aber irgendwie auch nicht zu finden

    http://de.wikipedia.org/wiki/C%2B%2B-Standardbibliothek


Anmelden zum Antworten