2015-03-12 13 views
7

Ich versuche, eine Datei für die Ausgabe zu öffnen und an sie anzuhängen. Nach dem Anhängen möchte ich meine Ausgabeposition an anderer Stelle in der Datei verschieben und existierende Daten überschreiben. Wie ich es verstehe, std::ios_base::app wird force schreibt alles am Ende der Datei, die ist nicht was ich tun möchte. Als solches glaube ich, std::ios_base::ate ist das richtige Flag, um an std::ofstream::open() zu übergeben. Allerdings scheint es, wird nicht wie erwartet funktioniert:Std :: Ofstream mit Std :: ate nicht am Ende öffnen

// g++ test.cpp 
// clang++ test.cpp 
// with and without -std=c++11 
#include <iostream> 
#include <fstream> 

int main() { 
    std::streampos fin, at; 
    { 
     std::ofstream initial; 
     initial.open("test", std::ios_base::out | std::ios_base::binary); 
     if (not initial.good()) { 
      std::cerr << "initial bad open" << std::endl; 
      return 1; 
     } 
     int b = 100; 
     initial.write((char*)&b, sizeof(b)); 
     initial.flush(); 
     if (not initial.good()) { 
      std::cerr << "initial write bad" << std::endl; 
      return 1; 
     } 
     fin = initial.tellp(); 
    } 
    { 
     std::ofstream check; 
     check.open("test", std::ios_base::out | std::ios_base::binary | std::ios_base::ate); 
     if (not check.good()) { 
      std::cerr << "check bad open" << std::endl; 
      return 1; 
     } 
     at = check.tellp(); 
     if (fin != at) { 
      std::cerr << "opened at wrong position!\nfin:\t" << fin << "\n" << "at:\t" << at << std::endl; 
      return 1; 
     } 
     int bb = 200; 
     check.write((char*)&bb, sizeof(bb)); 
     check.flush(); 
     if (not check.good()) { 
      std::cerr << "check write bad" << std::endl; 
      return 1; 
     } 
     at = check.tellp(); 
    } 
    if ((fin + std::streampos(sizeof(int))) != at) { 
     std::cerr << "overwrite?\nfin:\t" << fin << "\n" << "at:\t" << at << std::endl; 
     return 1; 
    } 
    return 0; 
} 

Insbesondere scheint es, dass std::ios_base::ate tut nicht bewegen die anfänglichen Ausgabezeiger auf das Ende mit dem Beispiel oben gesehen. Offensichtlich würde dies dazu führen, dass der erste Schreibvorgang den Anfang der Datei überschreibt (was meine Probleme verursacht hat).

Es scheint, dass entweder die Umsetzung nicht korrekt ist oder sonst cplusplus.com ist falsch („Die Ausgangsposition am Ende der Datei beginnt.“) und cppreference.com ist nicht eindeutig („bis zum Ende des Stromes suchen Sie sofort nach offen ": welcher Stream?".

Es gibt natürlich eine einfache Abhilfe: Verwenden Sie einfach stream.seekp(0, std::ios_base::end).

Also meine Frage ist also: ist mein Code falsch? Ist die Implementierung falsch? Sind die Referenzstellen falsch? Jeder Einblick würde geschätzt werden.

+2

http://en.cppreference.com/w/cpp/io/ verkürzt werden basic_filebuf/öffnen. Verwenden von "out" ohne "app" oder "in" schneidet ab. –

Antwort

7

Wie Sie aus der folgenden Tabelle in N4296 [filebuf.members]

file io

Die Kombination sehen binary | out wird die Datei im stdio äquivalent "wb" öffnen, die truncate to zero length or create binary file for writing (N1570 7.21.5.2).

Wie eingängig wie es für einen ofstream klingt, müssen Sie die in Flag hinzufügen, wenn Sie möchten, dass Ihre Datei nicht abgeschnitten oder app werden, wenn Sie Abschneiden vermeiden wollen und auf das Ende der Datei suchen Jeder schreibt.

Bonus-Tipp: Im Gegensatz zu fstream, ifstream und ofstream automatisch oder std::ios_base::in und std::ios_base::out jeweils mit beliebigen Flags, die Sie an den Konstruktor zur Verfügung stellen oder zu open. Sie können auch das Objekt verwenden, selbst die Fahnen zuzugreifen:

std::ofstream check("test", check.in | check.binary | check.ate); 

Die Kontrollen für good kann auch auf if (!initial) usw.

+2

Oh derp. Das * total * macht Sinn ... benutze das Eingabe-Flag, um nicht abzukürzen, wenn es eine bestimmte Ebene zum Abschneiden gibt. Ganzer Sinn genau dort. Es war das Problem. Vielen Dank :) – inetknght

Verwandte Themen