End of File - behindet ofstream?



  • Hoi!

    Ich möchte:
    - Datei Zeichenweise einlesen
    - und in eine andere Datei schreiben

    Das Problem:
    Datei wird zwar erstellt - zeichen wird in die "schreiben"-funktion richtig übergeben - aber werden danach nich in die datei geschrieben!

    void eoffkt(string dateinamein, string dateinameout)
    {
       cout<<"dateinamein: "<<dateinamein<<endl;  
       cout<<"dateinameout: "<< dateinameout<<endl;
       fflush(stdin);
       getchar();
    
       ifstream htmldatei;  
       htmldatei.open(dateinamein.c_str());
    
       char zeichen;
    
       while(!htmldatei.eof())
       {
         htmldatei.get(zeichen);
         char_schreiben(zeichen,dateinameout);   
       }   
    
       htmldatei.close();
    }
    void schreiben(char zeichen, string dateiname)
    {  
       cout<<"char_schreiben("<<zeichen<<")"<<endl;  
       ofstream txtdatei;
       txtdatei.open(dateiname.c_str(), ios::out|ios::app);
    
                txtdatei<<zeichen;
    
       txtdatei.close();       
    }
    

    Ich bedanke mich in voraus für eure Bemühungen!

    MfG ~ SITDnow



  • fstream::eof() wird nicht zwangsläufig true, wenn das letzte Zeichen im Stream gelesen wurde. Bei manchen streams ist es für C++ nicht feststellbar, ob das letzte Zeichen bereits gelesen wurde, oder nicht. Z.B. bei Tastatureingaben. Daher kann es sein, dass eof erst true wird, wenn hinter dem letzten Zeichen gelesen wird.
    Besser ist es so:

    void eoffkt(string dateinamein, string dateinameout)
    {
       cout << "dateinamein: " << dateinamein << endl;  
       cout << "dateinameout: " << dateinameout << endl;
       //fflush(stdin); //fflush ist zum sofortigen leeren von Puffern von Ausgabestreams. 
                        //Für Eingabepuffer ist es UNDEFINIERT
       //getchar(); //Wozu?
    
       ifstream htmldatei(dateinamein.c_str()); //kann man hier schon angeben
       //htmldatei.open(dateinamein.c_str()); //unnoetig (s.o.)
    
       char zeichen;
    
       //besser so:
       while(htmldatei.get(zeichen))
       {
         //htmldatei.get(zeichen);
         char_schreiben(zeichen,dateinameout);  
       }  
    
       //htmldatei.close(); //Ueberfluessig. Wird automatisch beim Verlassen der Funktion geschlossen
    }
    


  • Danke für deine Antwort ^^

    Aber leider besteht das Problem weiterhin > es wird lediglich eine leere Datei erstellt...

    (das getchar() war nur dazu da damit ich üperprüfen kann ob die dateinamen richitg waren (also gings erst weiter wenn man enter drückt - und ohne das fflush(stdin) macht getchar meist probleme - zb. wenn es das zweite mal aufgerufen wird)



  • SITDnow schrieb:

    Danke für deine Antwort ^^

    Aber leider besteht das Problem weiterhin > es wird lediglich eine leere Datei erstellt...

    (das getchar() war nur dazu da damit ich üperprüfen kann ob die dateinamen richitg waren (also gings erst weiter wenn man enter drückt - und ohne das fflush(stdin) macht getchar meist probleme - zb. wenn es das zweite mal aufgerufen wird)

    Wie gesagt, das Verhalten beim Flushen von Eingabestreams ist ebenso undefiniert, wie das Lesen und Schreiben in Speicherbereichen, die einem nicht gehören. Das heisst: nicht machen!
    Das mit den istreams und den Resten im Puffer ist etwas kniffelig. Am Besten wartet man so:

    std::cin.putback('\n'); //mindestens '\n' ist jetzt im Stream
    std::cin.clear();   //Alle Flags loeschen (Fehler etc.)
    std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); //Den Stream leeren, entweder alles oder bis '\n'
    std::cin.get(); //Warten
    

    Wie sieht denn die Funktion char_schreiben(zeichen,dateinameout) aus? Vermutlich liegt der Fehler da.



  • Ich hab beim Beitrag schreiben die Funktionsnamen geändert, und dabei den Aufruf vergessen ^^"

    char_schreiben = schreiben

    also so:

    void char_schreiben(char zeichen, string dateiname)
    {  
       cout<<"char_schreiben("<<zeichen<<")"<<endl;  
    // nur um zu sehen ob ein zeichen übernommen wurde (Zeichen werden richtig übernommen)
    
       ofstream txtdatei;
       txtdatei.open(dateiname.c_str(), ios::out|ios::app);
    
                txtdatei<<zeichen;
    
       txtdatei.close();      
    }
    

    Danke für die Flush Erläuterung 🙂



  • SITDnow schrieb:

    ...

    Ich tippe mal darauf, dass der ifstream nicht richtig geöffnet wird (falscher Dateiname z.B.).
    Bau mal eine Prüfung ein:

    //in void eoffkt(...)
    //...
    ifstream htmldatei(dateinamein.c_str());
    if(!htmldatei)
    {
       std::cerr << "Fehler beim oeffnen!\n";
       return;
    }
    //...
    

    Das Ganze ist eh noch recht suboptimal.
    Die std::strings würde ich als Referenzen übergeben:

    void eoffkt( const string& dateinamein, const string& dateinameout)
    {/*...*/}
    

    Sonst muss der String bei jedem Aufruf kopiert werden, was nicht notwendig ist.
    Außerdem solltest Du Dir vielleicht einen Mechanismus ausdenken, bei dem der ofstream nicht bei jedem Aufruf von char_schreiben geöffnet und geschlossen werden muss.



  • Der Dateiname wird schon in der Funktion die den Dateinamen einliest geprüft - und wie gesagt werden die Zeichen richtig eingelesen und auch in die "char_schreiben" Funktion übergeben.

    Lediglich das schreiben in die Datei geht dann nicht mehr
    (Auch ein txtdatei<<"bla bla"; wird nicht in die Datei geschrieben...)

    Sicher könnte ich auch die beiden Funktionen vereinen.
    Also beide f-Streams öffnen und dann die Schleife mit txtdatei<<zeichen; ausführen.

    Nur das Problem besteht dann auch noch weiterhin...

    Kann man file-streams flushen? Bzw. könnte es damit etwas zu tun haben?



  • SITDnow schrieb:

    Der Dateiname wird schon in der Funktion die den Dateinamen einliest geprüft - und wie gesagt werden die Zeichen richtig eingelesen und auch in die "char_schreiben" Funktion übergeben.

    Es geht nicht um den Dateinamen, sondern darum, ob die Datei korrekt geöffnet wurde. Bei mir geht der Code, sofern die Datei auch zu finden und zu öffnen ist.
    Und flushen musst Du da nichts. Das passiert spätestens beim close()/Destruktor des STreams.



  • Es wird tatsächlich ein Fehler Angezeigt... aber woran liegts? (Die Datei ist vorhanden sonst könnt er sie ja nicht einlesen und die Zeichen richtig weiter geben, oder???)

    Ich hab mal alles stark vereinfacht.
    Aber ich denke das der Fehler der selbe ist wie bei diesen beiden Beispielen:

    Dieses Beispiel Funktioniert:

    #include <iostream>
    #include <fstream>
    #include <string>
    
    using namespace std;
    
    int main()
    {
       string dateinameIN,dateinameOUT;
       char zeichen;
    
       cout<<"Eingabe Input-Datei"<<endl;
       cin>>dateinameIN;
       cout<<"Eingabe Output-Datei"<<endl;
       cin>>dateinameOUT;
    
       ifstream indatei(dateinameIN.c_str()); 
       ofstream outdatei(dateinameOUT.c_str(), ios::out|ios::app);
    
       while(indatei.get(zeichen))
            outdatei<<zeichen;
    }
    

    Und dieses Erweiterung nicht:

    #include <iostream>
    #include <fstream>
    #include <string>
    
    using namespace std;
    
    int main()
    {
       string dateinameIN,dateinameOUT;
       char zeichen;
    
       cout<<"Eingabe Input-Datei"<<endl;
       cin>>dateinameIN;
       cout<<"Eingabe Output-Datei"<<endl;
       cin>>dateinameOUT;
    
       ifstream indatei(dateinameIN.c_str()); 
       ofstream outdatei(dateinameOUT.c_str(), ios::out|ios::app);
    
       bool jump=0;
       while(indatei.get(zeichen))
       {
         if(zeichen='<')
            {
                        jump=1;
                        cout<<"<";
            }
    
         if(jump==0)   
            outdatei<<zeichen;
    
         if(zeichen='>')
            {
            jump=0;
            cout<<">";
            }
       }  
    }
    


  • SITDnow schrieb:

    Und dieses Erweiterung nicht:

    #include <iostream>
    #include <fstream>
    #include <string>
    
    using namespace std;
    
    int main()
    {
       string dateinameIN,dateinameOUT;
       char zeichen;
       
       cout<<"Eingabe Input-Datei"<<endl;
       cin>>dateinameIN;
       cout<<"Eingabe Output-Datei"<<endl;
       cin>>dateinameOUT;
       
       ifstream indatei(dateinameIN.c_str());
       //hier pruefen, ob das Oeffnen erfolgreich war!!
       ofstream outdatei(dateinameOUT.c_str(), ios::out|ios::app);
       //hier pruefen, ob das Oeffnen erfolgreich war!!
       
       bool jump=0; //false anstatt 0
       while(indatei.get(zeichen))
       {
         if(zeichen='<') // == anstatt = ( ist so immer true!)
            {
                        jump=1; //true statt 1 (ist wegen oben immer true)
                        cout<<"<";
            }
    
         if(jump==0) //false anstatt 0
            outdatei<<zeichen;
    
         if(zeichen='>') // == anstatt =
            {
            jump=0; //false anstatt 0
            cout<<">";
            }
       }  
    }
    


  • Okay das war ein schönes beispiel dafür das man nichts zwischen Tür und Angel schreiben sollte... dann klappts auch im Projekt:
    Aber wo war nun der Fehler?? An den Dateinamen hab ich nichts gedreht.

    void eoffkt(string dateinameIN,string dateinameOUT)
    {
       char zeichen;  
       cout<<"dateinamein: "<<dateinameIN<<endl;  
       cout<<"dateinameout: "<< dateinameOUT<<endl;
    
       ifstream indatei(dateinameIN.c_str()); 
       ofstream outdatei(dateinameOUT.c_str(), ios::out|ios::app);
    
       bool jump=false;
       while(indatei.get(zeichen))
       {
         if(zeichen=='<')
            {
                        jump=true;
                        cout<<"<";
            }
         if(jump==false)   
            outdatei<<zeichen;
    
         if(zeichen=='>')
            {
                       jump=false;
                       cout<<">";
            }
       }  
    }
    

Anmelden zum Antworten