设置标准流使用的内部缓冲区(pubsetbuf)

Ste*_*idi 24 c++ stream visual-c++

我正在编写一个需要将数据写入现有缓冲区的子程序,我想使用stringstream该类来简化数据的格式化.

最初,我使用以下代码将流的内容复制到缓冲区,但是希望避免这种解决方案,因为它复制了太多数据.

#include <sstream>
#include <algorithm>

void FillBuffer(char* buffer, unsigned int size)
{
    std::stringstream message;
    message << "Hello" << std::endl;
    message << "World!" << std::endl;

    std::string messageText(message.str());
    std::copy(messageText.begin(), messageText.end(), buffer);
}
Run Code Online (Sandbox Code Playgroud)

这是我发现streambuf::pubsetbuf()方法的时候,简单地重写上面的代码如下.

#include <sstream>

void FillBuffer(char* buffer, unsigned int size)
{
    std::stringstream message;
    message.rdbuf()->pubsetbuf(buffer, size);

    message << "Hello" << std::endl;
    message << "World!" << std::endl;
}
Run Code Online (Sandbox Code Playgroud)

不幸的是,这在Visual Studio 2008附带的C++标准库实现下不起作用; buffer保持不变.

我看了一下它的实现,pubsetbuf结果发现它实际上"什么都不做".

virtual _Myt *__CLR_OR_THIS_CALL setbuf(_Elem *, streamsize)
{   // offer buffer to external agent (do nothing)
    return (this);
}
Run Code Online (Sandbox Code Playgroud)

这似乎是给定C++标准库实现的限制.配置流以将其内容写入给定缓冲区的推荐方法是什么?

Ste*_*idi 19

在对这个问题进行了一些研究,并仔细审查了我的代码后,我发现了一个帖子,建议使用手工编写的std::streambuf类.这段代码背后的想法是创建一个streambuf初始化其内部结构以引用给定的缓冲区.代码如下.

#include <streambuf>

template <typename char_type>
struct ostreambuf : public std::basic_streambuf<char_type, std::char_traits<char_type> >
{
    ostreambuf(char_type* buffer, std::streamsize bufferLength)
    {
        // set the "put" pointer the start of the buffer and record it's length.
        setp(buffer, buffer + bufferLength);
    }
};
Run Code Online (Sandbox Code Playgroud)

现在,如果您查看我的原始代码,您会注意到我并不需要stringstream开头.我真正需要的只是一种使用IOStream库写入外部缓冲区的方法,并且std::ostream是解决此问题的更好的类型.顺便说一句,我怀疑这是怎么了array_sink从类型了Boost.Iostreams实现.

这是使用我的ostreambuf类型的修改代码.

#include <ostream>
#include "ostreambuf.h"  // file including ostreambuf struct from above.

void FillBuffer(char* buffer, unsigned int size)
{
    ostreambuf<char> ostreamBuffer(buffer, size);
    std::ostream messageStream(&ostreamBuffer);

    messageStream << "Hello" << std::endl;
    messageStream << "World!" << std::endl;
}
Run Code Online (Sandbox Code Playgroud)


Éri*_*ant 5

看起来像是(正式弃用,但仍然是标准的)std::strstream 的工作。您还可以查看Boost.IOStreams库,特别是array_sink