C ++中的复合std :: istream

时间:2013-10-21 23:13:29

标签: c++ boost stl iostream

我有一个std::istream对象列表,我需要将其显示为单个std::istream对象。所以,如果我有三个istream s,A,B和C,我希望能够创建一个istream,D首先从A返回字节,然后从B返回字节,然后再返回C已到达EOF。在读取所有字节后,将始终按顺序读取复合流并将其关闭。

使用stl / boost是否有一种简单的方法可以做到这一点,或者我只需要编写自己的复合istream吗?

1 个答案:

答案 0 :(得分:0)

另一个问题(https://stackoverflow.com/a/17103292/1424877)的非主题回答可能会对您有所帮助。

#include <iostream>
#include <string>
#include <sstream>

class ConcatStreams : public std::streambuf
{
    int useBuf;
    std::streambuf *sbuf_[2];
    char buffer_[1024];

  public:
    ConcatStreams(std::istream& sbuf1, std::istream& sbuf2) :
        useBuf(0), sbuf_{sbuf1.rdbuf(), sbuf2.rdbuf()}
    { }

    int underflow()
    {
        if (this->gptr() == this->egptr()) {
            std::streamsize size = 0;
            while (useBuf < 2) {
                size = this->sbuf_[useBuf]->sgetn(this->buffer_, sizeof this->buffer_);
                if (!size) {
                    useBuf++;
                } else {
                    break;
                }
            } 
            this->setg(this->buffer_, this->buffer_, this->buffer_ + size);
        }
        return this->gptr() == this->egptr()
             ? std::char_traits<char>::eof()
             : std::char_traits<char>::to_int_type(*this->gptr());
    }
};

int main()
{
    std::istringstream is("hello world!\n");

    ConcatStreams cs_(is, std::cin); // prepend "hello world" to the input
    std::istream cs(&cs_);

    std::string s;
    while (cs >> s)
      std::cout << "'" << s << "'" << std::endl;
}

请注意,您无法使用此特定技巧将std::cin与其自身连接,甚至与自身连接is;但它应该可以很好地连接任何两个不同的输入流。您甚至可以连接多个ConcatStreams个实例!