2016-08-06 5 views
1

私はifstream.rdbuf()を使っていると何とか変わっているようです。次のコードは、問題を示す必要があります。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()を使用して別のものに1つのテキストファイルの内容をコピーしようとしているということです。これは正常に動作しますが、getline(ifs, str)を使用してifsから読み取りを行うと、ストリームが効果的に「破損」します。

+1

問題は何ですか?あなたはすでにファイルからすべてを読んだことがありますが、何か読んでいると思われるのはなぜですか? –

+4

あなたはあなたの呼び出しでストリームを消費したので、ファイルを巻き戻す必要があります:呼び出しの間に 'ifs.seekg(0);'を挿入してください。 –

+5

回答セクションは下にあります。 –

答えて

3

これは特に「奇妙な」わけではありません。それはあなたが毎日見るのと同じ流れの振る舞いです。あなたのストリームである

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; 

として:あなたは元のストリーム自身から読んでいまして、それはあなたのcoutはその後、ちょうどから読んでいることを、バッファへのポインタですrdbufstd::stringstream::str()ようにされていません、それは—魔法ではありませんファイルストリームでは、を最初から始めて探すことができます(これは、本質的にその基になるバッファに同じことを行います)。

+1

OPにもっとよく似た何かを使って同じ振る舞いを伝えます。よくやったよ。 – WhozCraig

2

ifs.rdbuf()は、ifsの対応するストリームバッファオブジェクトへのポインタを返します。 overloadは、バッファの終わり(eof)に達するまでストリームから情報を引き出します。 .rdbuf()を呼び出すと、バッファの最後には何も読み込めないので、何も返されません。バッファシーク位置は、ifs.seekg (0);を呼び出すことによって明示的にゼロにリセットされます。

+3

注: 'ifs.rdbuf()'を呼び出すだけでは、シーク位置が前進しません。ストリームに関連付けられたストリームバッファオブジェクトへのポインタを返します。それは、後でそのポインタ*で行われることです。この場合、 'operator <<' overloadを介して 'std :: cout'に送信します。このオーバーロードは' eof'まで引き出し、ストリームバッファのseekg位置を進めます。要約すると、 'rdbuf()'の結果を、シーク位置を前進させているシンクに送ります。 'rdbuf()'によるバッファオブジェクトの取得は、一連のイベントの最初のステップにすぎません。 – WhozCraig

+0

私はこれをupvoteしたいですが、Wh​​ozCraigは正しいです - それは現時点では不正確です。 –