ifstreams和rdbuf()的怪异行为

时间:2021-07-16 17:26:24

I've noticed that using .rdbuf() on an ifstream seems to change it somehow. The following code should show the problem.

我注意到在ifstream上使用.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;
}

The reason this is bothering me is that I'm currently trying to copy the contents of one text file into another using ofstream ofs; ofs << ifs.rdbuf(). This works fine but makes reading from ifs using getline(ifs, str) fail, effectively "breaking" the stream.

这让我感到困扰的原因是,我目前正在尝试将一个文本文件的内容复制到另一个使用ofs的文本文件中;ofs < < ifs.rdbuf()。这样做很好,但是使用getline(ifs, str)失败,有效地“破坏”了流。

2 个解决方案

#1


3  

This isn't particularly "weird"; it's the same stream behaviour you see every day. rdbuf isn't like std::stringstream::str() and it isn't magic — it's a pointer to the buffer, that your cout is then reading from just as you would read from the original stream yourself:

这不是特别“怪异”;这是你每天都看到的同样的潮流。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;

As your stream is a file stream, you can seek it back to the beginning to start from scratch (which will inherently do the same to its underlying buffer).

当您的流是一个文件流时,您可以将它返回到从头开始(这将从本质上对它的底层缓冲区起同样的作用)。

#2


2  

ifs.rdbuf() returns a pointer to the ifs's corresponding stream buffer object. Sending it to std::cout via << overload pulls information from the stream until the end of the buffer is reached (eof). Calling .rdbuf() again returns "nothing" because there's nothing to read at the end of the buffer. The buffer seek position be explicitly reset to zero by calling ifs.seekg (0);.

rdbuf()返回一个指向ifs相应的流缓冲对象的指针。发送到std::cout通过< <重载从流中提取信息,直到缓冲区的结束到达(eof)。调用.rdbuf()再次返回“nothing”,因为在缓冲区的末尾没有什么可读的。通过调用ifs显式地将缓冲区查找位置重置为零。seekg(0);。< p>

#1


3  

This isn't particularly "weird"; it's the same stream behaviour you see every day. rdbuf isn't like std::stringstream::str() and it isn't magic — it's a pointer to the buffer, that your cout is then reading from just as you would read from the original stream yourself:

这不是特别“怪异”;这是你每天都看到的同样的潮流。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;

As your stream is a file stream, you can seek it back to the beginning to start from scratch (which will inherently do the same to its underlying buffer).

当您的流是一个文件流时,您可以将它返回到从头开始(这将从本质上对它的底层缓冲区起同样的作用)。

#2


2  

ifs.rdbuf() returns a pointer to the ifs's corresponding stream buffer object. Sending it to std::cout via << overload pulls information from the stream until the end of the buffer is reached (eof). Calling .rdbuf() again returns "nothing" because there's nothing to read at the end of the buffer. The buffer seek position be explicitly reset to zero by calling ifs.seekg (0);.

rdbuf()返回一个指向ifs相应的流缓冲对象的指针。发送到std::cout通过< <重载从流中提取信息,直到缓冲区的结束到达(eof)。调用.rdbuf()再次返回“nothing”,因为在缓冲区的末尾没有什么可读的。通过调用ifs显式地将缓冲区查找位置重置为零。seekg(0);。< p>