2012-09-11 5 views
14

Für die Ausführung von Datei IO in C++ verwenden wir die Ofstream, Ifstream und Fstream Klassen.C++ - Datei Stream offene Modi Mehrdeutigkeit

  • ofstream: Stream-Klasse auf Dateien
  • ifstream schreiben: Stream-Klasse Lesen und Schreiben von/nach Dateien

Die: Stream-Klasse von Dateien

  • fstream lesen Prozess der Zuordnung einer Datei zu einem Stream-Objekt heißt "Öffnen der Datei". Beim Öffnen einer Datei können wir den Modus angeben, in dem die Datei geöffnet werden soll. Meine Abfrage bezieht sich auf die Modi ios::out und ios:in.

    Wenn ich ein ofstream Objekt und öffnen Sie die Datei mit ios::in Modus erstellen, ich bin zu schreiben in die Datei kann aber nur, wenn seine bereits (mit ios::out Modus Datei wird auch erstellt, wenn es nicht bereits vorhanden ist).
    Aber wenn ich ifstream Objekt erstellen und die Datei mit ios::out Modus öffnen, kann ich aus der Datei lesen.

    Meine Frage ist, warum diese Modi (ios::in/ios::out) durch die Sprache geliefert werden, wenn die Art des Stromes (ifstream/ofstream) selbst als zu der Art der Operation spezifiziert (Eingabe/Ausgabe) durchgeführt wird?

    auch, warum diese zweideutige Verwendung (ofstream mit ios::in und ifstream mit ios::out) in einem Fall arbeitet und nicht (wenn auch nur, wenn die Datei nicht bereits vorhanden ist) in einem anderen?

  • Antwort

    11

    Die ofstream, ifstream und fstream Klassen sind hohe Schnittstellen für den Untergebener filebuf, die man durch die rdbuf() Memberfunktion des Stroms zu erhalten.

    Gemäß dem Standard, wenn Sie einen ofstream mit einem Modus mode öffnen, öffnet es den Unterstreichungsstrompuffer wie mit mode | ios_base::out. Analog verwendet ifstreammode | ios_base::in. fstream übergibt den mode Parameter wörtlich an den Unterstreichungsstrompuffer.

    Was die oben impliziert ist, dass der folgende Code die Datei mit genau den gleichen offenen Fahnen öffnet:

    fstream f("a.txt", ios_base::in | ios_base::out); 
    ifstream g("a.txt", ios_base::out); 
    ofstream h("a.txt", ios_base::in); 
    

    Nach diesen Zeilen, die Sie tun können, genau die gleichen Dinge mit f.rdbuf(), g.rdbuf() und h.rdbuf() und all drei fungieren, als ob Sie die Datei mit dem C-Aufruf fopen("a.txt", "r+") geöffnet haben, der Ihnen Schreib-/Lesezugriff gewährt, die Datei nicht abschneidet und fehlschlägt, wenn die Datei nicht existiert.

    Also, warum haben wir drei verschiedene Klassen? Wie ich bereits sagte, sind dies High-Level-Klassen, die eine High-Level-Schnittstelle über den unteren Stream-Puffer bieten. Die Idee ist, dass ifstream Member-Funktionen für die Eingabe (wie read()), ofstream hat Member-Funktionen für die Ausgabe (wie write()) während fstream hat beide. Zum Beispiel können Sie dies nicht tun:

    g.write("abc", 3); // error: g does not have a write function 
    

    Aber das funktioniert, weil, obwohl g ein ifstream ist, dass wir es mit ios_base::out geöffnet hatte:

    g.rdbuf()->sputn("abc", 3); // we still have write access 
    
    0

    Da der Modus nicht auf Eingabe/Ausgabe beschränkt ist. Der Konstruktor von ifstream zum Beispiel wie folgt aussieht:

    explicit ifstream (const char * filename, ios_base::openmode mode = ios_base::in); 
    

    Hinweis der Standardwert ios_base::in ist, so müssen Sie es selbst nicht angeben. Allerdings setzt die mode die Ströme Flags, die nicht beschränkt aufin/out sind, aber umfassen:

    • app (append) Stellen des Positionsanzeiger des Stroms bis zum Ende des Stroms vor jedem Ausgabevorgang.
    • ate (am Ende) Stellen Sie die Positionsanzeige des Streams auf das Ende des Stroms beim Öffnen ein.
    • binary (Binär) Betrachte Stream als binär und nicht als Text.
    • in (Eingabe) Erlaube Eingabeoperationen im Stream.
    • out (Ausgabe) Erlaube Ausgabevorgänge im Stream.
    • trunc (abgeschnitten) Jeder aktuelle Inhalt wird verworfen, wenn beim Öffnen eine Länge von Null angenommen wird.