2016-08-06 28 views
1

Ich habe festgestellt, dass mit .rdbuf() auf einem ifstream scheint es irgendwie zu ändern. Der folgende Code sollte das Problem zeigen.Weird Verhalten mit ifstreams und rdbuf()

#include <fstream> 
#include <iostream> 

using namespace std; 

int main(int argc, const char * argv[]) { 
    ifstream ifs("Sample.csv"); 
    cout << "Reading buffer: " << endl; 
    cout << ifs.rdbuf(); // Outputs buffer as expected 
    cout << "Reading buffer again: " << endl; 
    cout << ifs.rdbuf(); // Returns nothing 

    return 0; 
} 

Der Grund, warum dies stört mich ist, dass ich zur Zeit versucht, den Inhalt einer Textdatei in eine andere ofstream ofs; ofs << ifs.rdbuf() mit zu kopieren. Das funktioniert gut, aber das Lesen von ifs unter Verwendung von getline(ifs, str) schlägt fehl und "bricht" effektiv den Stream.

+1

Was ist das Problem? Du hast schon alles aus einer Datei gelesen, warum erwartest du etwas zu lesen? –

+4

Sie müssten die Datei zurückspulen, weil Sie den Stream mit Ihrem Aufruf verbraucht haben: Fügen Sie 'ifs.seekg (0);' zwischen den Aufrufen ein. –

+5

Antwortabschnitt ist unten. –

Antwort

3

Dies ist nicht besonders "komisch"; Es ist das gleiche Stream-Verhalten, das man jeden Tag sieht. rdbuf nicht std::stringstream::str() mögen und es ist keine Zauberei — es ist ein Zeiger auf den Puffer, dass Ihr cout dann von gerade liest, wie Sie aus dem ursprünglichen Strom selbst lesen würde:

std::stringstream ss("1"); 
int x; 
if (ss >> x) 
    cout << x; 
if (ss >> x) // doesn't work a second time; "1" is already extracted 
    cout << x; 

Als Stream a Datei-Stream, können Sie suchen es zurück an den Anfang, um von Grund auf neu zu starten (was inhärent das gleiche zu seinem zugrunde liegenden Puffer zu tun).

+1

Übermittlung des gleichen Verhaltens unter Verwendung von etwas, das dem OP sehr wahrscheinlich vertrauter ist; Gut gemacht, mein Herr. – WhozCraig

2

ifs.rdbuf() gibt einen Zeiger auf das entsprechende Strompufferobjekt ifs zurück. Senden an std::cout über << Überladung zieht Informationen aus dem Strom, bis das Ende des Puffers erreicht ist (eof). Beim Aufruf von .rdbuf() wird wieder "nichts" zurückgegeben, da am Ende des Puffers nichts zu lesen ist. Die Puffer-Suchposition wird durch Aufruf von ifs.seekg (0); explizit auf Null zurückgesetzt.

+3

Hinweis: Wenn Sie nur 'ifs.rdbuf() 'aufrufen, wird die Suchposition nicht weitergeführt. Es gibt einfach einen Zeiger auf das Strompufferobjekt zurück, das dem Stream zugeordnet ist. Es kommt darauf an, was mit diesem Zeiger * danach gemacht wird. In diesem Fall senden Sie es an 'std :: cout' über eine' operator << 'overload, die von ihm bis' eof' zieht und dabei die seekg Position im stream Buffer vorrückt. Kurz gesagt, es sendet das Ergebnis von 'rdbuf()' an eine Senke, die ihre Suchposition voranbringt. Die Erfassung des Pufferobjekts durch 'rdbuf()' ist nur der erste Schritt in dieser Reihe von Ereignissen. – WhozCraig

+0

Ich würde das gern aufwerten, aber WhozCraig hat Recht - im Moment ist es ungenau. –