2016-08-06 6 views
1

Я заметил, что использование .rdbuf() на ifstream похоже каким-то образом изменило его. Следующий код должен показать проблему.Странное поведение с ifstreams и 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; 
} 

Причина это беспокоит меня, что я в настоящее время пытается скопировать содержимое одного текстового файла в другой с помощью ofstream ofs; ofs << ifs.rdbuf(). Это отлично работает, но делает чтение с ifs с использованием getline(ifs, str) неудачным, эффективно «разбивая» поток.

+1

В чем проблема? Вы уже все прочитали из файла, почему вы ожидаете, что что-то останется читать? –

+4

вам потребуется перемотать файл, потому что вы потребляли поток с помощью своего вызова: вставьте 'ifs.seekg (0);' между вызовами. –

+5

Раздел ответов приведен ниже. –

ответ

3

Это не особенно «странно»; это то же поведение потока, которое вы видите каждый день. rdbuf не нравится std::stringstream::str() и это не магия — это указатель на буфер, что ваш cout затем чтение из так же, как вы бы читать из исходного потока сами:

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; 

Как ваш поток является файловый поток, вы можете искать обратно в начало, чтобы начать с нуля (что по своей сути сделает то же самое с его базовым буфером).

+1

Передача такого же поведения с использованием чего-то очень вероятно более знакомого OP; молодец, сэр. – WhozCraig

2

ifs.rdbuf() возвращает указатель на соответствующий буферный объект потока ifs. Отправляя его на std::cout через <<, перегрузка вытягивает информацию из потока до тех пор, пока не будет достигнут конец буфера (eof). Вызов .rdbuf() снова возвращает «ничего», потому что в конце буфера читать нечего. Позиция поиска буфера должна быть явно сброшена до нуля, вызвав ifs.seekg (0);.

+3

Примечание: просто вызов 'ifs.rdbuf()' не продвигает позицию поиска. Он просто возвращает указатель на объект буфера потока, связанный с потоком. Это то, что делается с этим указателем * после этого *, что имеет значение. В этом случае вы отправляете его в 'std :: cout' через перегрузку' operator << ', которая будет тянуть его до' eof', продвигая позицию seekg в буфере потока, делая это. Короче говоря, он отправляет результат 'rdbuf()' в раковину, которая продвигает свой поиск pos. Приобретение буферного объекта с помощью 'rdbuf()' является только первым шагом в этой серии событий. – WhozCraig

+0

Я хотел бы поддержать это, но WhozCraig прав - сейчас это неточно. –