Ausgabe mit Datein



  • Habe das nun so:

    #include <iostream>
    #include <fstream>
    
    using namespace std;
    
    int main(){
    
        ofstream ausgabe("test.txt");
        ausgabe << "Haus" << endl;
        ausgabe.close();
        return 0;
    }
    

    Ich bekomme auch keinen Fehler mehr angezeigt, es klappt auch.
    Ist das denn so richtig?



  • Ein char ist im Prinzip 1 Byte, d.h. du liest aus der einen Datei jedes byte und schreibst es in die andere... kenne Leute, die da gerne schreiben würden

    for(char ch; quelle.get(ch);)
        ziel.put(ch);
    

    ^^



  • hardware schrieb:

    kenne Leute, die da gerne schreiben würden

    for(char ch; quelle.get(ch); ziel.put(ch))
    


  • Skeptar schrieb:

    Habe das nun so:

    #include <iostream>
    #include <fstream>
    
    using namespace std;
    
    int main(){
    
        ofstream ausgabe("test.txt");
        ausgabe << "Haus" << endl;
        ausgabe.close();
        return 0;
    }
    

    Ich bekomme auch keinen Fehler mehr angezeigt, es klappt auch.
    Ist das denn so richtig?

    Wenn du einen Zeilenumbruch willst, nutze '\n' statt endl
    ausgabe.close() kannst du weglassen, passiert automatisch, wenn ausgabe "out of scope" geht
    LG

    P.S.: Sorry für meine zu vielen Posts, sollte mich mal einloggen, damit ich editieren kann^^



  • Skeptar schrieb:

    Habe das nun so:

    #include <iostream>
    #include <fstream>
    
    using namespace std;
    
    int main(){
    
        ofstream ausgabe("test.txt");
        ausgabe << "Haus" << endl;
        ausgabe.close();
        return 0;
    }
    

    Ich bekomme auch keinen Fehler mehr angezeigt, es klappt auch.
    Ist das denn so richtig?

    Rein formal ja.
    Allerdings zwei Dinge:
    - endl ist nicht einfach nur eine Ausgabe von '\n', es wird auch geflusht. Meistens willst du das nicht, deswegen schreib einfach nur '\n'
    - du musst den Stream nicht closen, das erledigt der Destruktor von ofstream automatisch

    Edit: Verdammt, zu spät.



  • Okey danke.
    In der Schule hat der Lehrer uns das mit << endl; beigebracht. Ich versuche jedzt immer \n zu schreiben aber klappt nicht immer wie man sieht. ABer es ist nicht falsch mit

    ausgabe.close();
    

    ?



  • Skeptar schrieb:

    Okey danke.
    In der Schule hat der Lehrer uns das mit << endl; beigebracht. Ich versuche jedzt immer \n zu schreiben aber klappt nicht immer wie man sieht. ABer es ist nicht falsch mit

    ausgabe.close();
    

    ?

    Es ist überflüssig.



  • Das Problem ist ganz offensichtlich das Buch. Was ließste denn da?



  • out schrieb:

    Das Problem ist ganz offensichtlich das Buch. Was ließste denn da?

    AH, da oben stehts ja, du ließt den Breymann. Der ist gut. Aber steht da echt open und close drin, und exit? 😃 Muss ich mal nachschauen.



  • Ja da steht halt das man das generell auch nicht machen muss 🙂
    Danke für die Hilfe :p



  • Aha 🙂 .... das wollt ich schon immer wissen:

    Nathan schrieb:

    Allerdings zwei Dinge:
    - endl ist nicht einfach nur eine Ausgabe von '\n', es wird auch geflusht. Meistens willst du das nicht, deswegen schreib einfach nur '\n'

    Ich beobachte, dass ein "\n" nicht reicht, um in einer DATEI in die nächste Zeile zu kommen, dafür klappts aber mit "\r\n" ...
    Den Unterschied zwischen \r und \n hab ich nicht verstanden ... 😕

    Auch nicht, warum es schlecht sein soll, den AUSGABEpuffer zu leeren.
    Ich meine, wenn es der Eingabepuffer wäre, kann ich das nachvollziehen, dass man den haben will und auch dass es gut ist, den mal zu leeren, man könnte ja womöglich noch seltsame Zeichen dadrin haben. Aber wozu braucht man den Ausgabepuffer noch, wenn man was ausgegeben hat ....?
    Bitte um Erleuchtung! 😕

    Ich häng mich mit der Frage mal an. (Wenn ihr das nicht wollt, mach ich eigenen Thread auf, aber ich denke, das ist grad im Sinne des Threaderstellers)



  • Lymogry schrieb:

    Auch nicht, warum es schlecht sein soll, den AUSGABEpuffer zu leeren.

    Ich finde das Wort flushen besser als leeren. Es ist eben sinnvoll, eine gewisse Menge an Zeichen zuerst in einem Puffer zu schreiben, und dann den gesamten Puffer in einem Rutsch rausschreiben, z.B. in eine Datei. Das ist viel effizienter, als jedes Zeichen einzeln rauszuschreiben. Wann es sinnvoll ist, den Puffer zu flushen, weiß dein Betriebssystem schon, da brauchst du kein endl das da rumpfuscht.



  • Lymogry schrieb:

    Aha 🙂 .... das wollt ich schon immer wissen:

    Nathan schrieb:

    Allerdings zwei Dinge:
    - endl ist nicht einfach nur eine Ausgabe von '\n', es wird auch geflusht. Meistens willst du das nicht, deswegen schreib einfach nur '\n'

    Ich beobachte, dass ein "\n" nicht reicht, um in einer DATEI in die nächste Zeile zu kommen, dafür klappts aber mit "\r\n" ...
    Den Unterschied zwischen \r und \n hab ich nicht verstanden ... 😕

    dann hast du die datei möglicherweise mit std::ios::binary geöffnet. wenn das der fall ist, dann werden '\n' nicht in "\r\n" (auf windows z.b.) konvertiert, damit man in einer bilddatei z.b. ein pixel so färben kann wie der entsprechende wert von '\n' hoch ist, ohne dass uns ofstream da ein '\r' reinpfuscht.

    Lymogry schrieb:

    Auch nicht, warum es schlecht sein soll, den AUSGABEpuffer zu leeren.
    Ich meine, wenn es der Eingabepuffer wäre, kann ich das nachvollziehen, dass man den haben will und auch dass es gut ist, den mal zu leeren, man könnte ja womöglich noch seltsame Zeichen dadrin haben. Aber wozu braucht man den Ausgabepuffer noch, wenn man was ausgegeben hat ....?
    Bitte um Erleuchtung! 😕

    Ich häng mich mit der Frage mal an. (Wenn ihr das nicht wollt, mach ich eigenen Thread auf, aber ich denke, das ist grad im Sinne des Threaderstellers)

    wenn du den ausgabepuffer flushesd, dann kann es z.b. sein dass dein programm dem os den befehl gibt, alles was noch im puffer ist direkt auf die festplatte zu schreiben. das ist sinnlos weil du ja nicht nach jeder zeile wieder den festplattenzugriff brauchst, das kann alles getrost im ram warten bis alles fertig ist.



  • Lymogry schrieb:

    Ich beobachte, dass ein "\n" nicht reicht, um in einer DATEI in die nächste Zeile zu kommen, dafür klappts aber mit "\r\n" ...
    Den Unterschied zwischen \r und \n hab ich nicht verstanden ... 😕

    Unter Windows besteht ein Zeilenumbruch in Dateien (nicht in stringstream) aus \r und \n. Wenn du eine Datei binär einließt, bekommst du beide Zeichen. Ließt du eine Datei im Textmodus ein, bekommst du nur das \n. Dass du aber für eine Ausgabe \r brauchst, ist mir neu 😕 .


  • Mod

    Lymogry schrieb:

    Ich beobachte, dass ein "\n" nicht reicht, um in einer DATEI in die nächste Zeile zu kommen, dafür klappts aber mit "\r\n" ...
    Den Unterschied zwischen \r und \n hab ich nicht verstanden ... 😕

    Öffne die Datei nicht binary!

    Auch nicht, warum es schlecht sein soll, den AUSGABEpuffer zu leeren.

    Weil du damit auslöst, dass die Daten physisch auf das Ausgabegerät geschrieben werden. Das ist langsam. Richtig langsam. Schnell ist es, wenn möglichst viel auf einmal geschrieben wird und dann auch noch am besten dann, wenn das dafür zuständige System meint, dass ein guter Zeitpunkt wäre. Denn die Menge macht nicht so viel aus, es ist der Zugriff an sich. Das machst du kaputt, wenn du nach jeder Zeile flusht. Denn dann sind das viel zu wenige Daten, als das ein Zugriff sich lohnen würde.



  • Lymogry schrieb:

    Nathan schrieb:

    Allerdings zwei Dinge:
    - endl ist nicht einfach nur eine Ausgabe von '\n', es wird auch geflusht. Meistens willst du das nicht, deswegen schreib einfach nur '\n'

    Ich beobachte, dass ein "\n" nicht reicht, um in einer DATEI in die nächste Zeile zu kommen, dafür klappts aber mit "\r\n" ...
    Den Unterschied zwischen \r und \n hab ich nicht verstanden ... 😕

    Das ist OS-abhängig. Manche OS brauchen '\n', andere '\r''\n'.
    Wenn du die Datei nicht im Binarymodus öffnest, kümmert sich ofstream um die Konvertierung, da musst du dir keine Gedanken machen. Ist das binary-Flag aber gesetzt, wird da nichts konvertiert, sondern Zeichen für Zeichen in die Datei geschrieben (Deswegen sollte man für Textausgabe ja nicht das binary Flag setzten, bei rohen Daten ist das wurscht). Das ist übrigens auch die einzige Besonderheit des binary Flags.

    Auch nicht, warum es schlecht sein soll, den AUSGABEpuffer zu leeren.
    Ich meine, wenn es der Eingabepuffer wäre, kann ich das nachvollziehen, dass man den haben will und auch dass es gut ist, den mal zu leeren, man könnte ja womöglich noch seltsame Zeichen dadrin haben. Aber wozu braucht man den Ausgabepuffer noch, wenn man was ausgegeben hat ....?
    Bitte um Erleuchtung! 😕

    IO von Dateien ist langsam. Da muss erst in Kernel Mode geswitcht werden, indem ein sycall ausgeführt wird, etc. (siehe hier).
    Würde das bei jedem Zeichen gemacht, was ausgegeben wird, wäre die Perfomance katastrophal. Deshalb werden die Zeichen erst einmal in einen Puffer geschrieben und der Puffer in die Datei, wenn er voll ist - oder wenn man flusht. flusht man bei jedem Newline auch wenn das überflüssig ist, zieht das die Perfomance runter.

    Edit: Oh, hab lang gebraucht den Beitrag zu schreiben.



  • Vielen Dank den tollen Antworten! 🙂

    Wenn ich das jetzt richtig verstehe, könnte endl sogar erzwingen, dass kurz vor einem Crash noch in eine Ausgabedatei geschrieben wird, während das mit \n womöglich noch nicht gemacht wurde? Vorausgesetzt man weiß, wo es buggt ..



  • Lymogry schrieb:

    Wenn ich das jetzt richtig verstehe, könnte endl sogar erzwingen, dass kurz vor einem Crash noch in eine Ausgabedatei geschrieben wird, während das mit \n womöglich noch nicht gemacht wurde? Vorausgesetzt man weiß, wo es buggt ..

    der destruktor von ofstream flushed natürlich auch (wer schreibt schon "<< std::flush" hin bevor er die datei schliesst?) und der wird ja auch noch aufgerufen wenn etwas wirft.



  • Lymogry schrieb:

    Vielen Dank den tollen Antworten! 🙂

    Wenn ich das jetzt richtig verstehe, könnte endl sogar erzwingen, dass kurz vor einem Crash noch in eine Ausgabedatei geschrieben wird, während das mit \n womöglich noch nicht gemacht wurde? Vorausgesetzt man weiß, wo es buggt ..

    Ja, bspw. bei einem Segfault ist es gut, wenn die Daten vorher geflusht werden.
    Aus diesem Grund ist cerr ja auch ungebuffert, eben das die letzten Fehlermeldungen noch sichtbar werden, bevor die Anwendung evtl. crasht.



  • Nathan schrieb:

    Lymogry schrieb:

    Vielen Dank den tollen Antworten! 🙂

    Wenn ich das jetzt richtig verstehe, könnte endl sogar erzwingen, dass kurz vor einem Crash noch in eine Ausgabedatei geschrieben wird, während das mit \n womöglich noch nicht gemacht wurde? Vorausgesetzt man weiß, wo es buggt ..

    Ja, bspw. bei einem Segfault ist es gut, wenn die Daten vorher geflusht werden.
    Aus diesem Grund ist cerr ja auch ungebuffert, eben das die letzten Fehlermeldungen noch sichtbar werden, bevor die Anwendung evtl. crasht.

    Ja genau, an den SegFault hab ich grad gedacht.

    Prima, dann gibt es ja sogar einen Anwendungsbereich für endl. 🙂 🙂


Log in to reply