代码之家  ›  专栏  ›  技术社区  ›  Steve Guidi

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

  •  23
  • Steve Guidi  · 技术社区  · 17 年前

    我正在编写一个需要将数据写入现有缓冲区的子例程,我希望使用 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);
    }
    

    这是我发现 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;
    }
    

    不幸的是,在VisualStudio 2008的C++标准库实现下,这是不起作用的; buffer 保持不变。

    我研究了 pubsetbuf 事实证明,它的字面意思是“什么都不做”。

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

    这似乎是给定C++标准库实现的一个限制。建议如何配置流以将其内容写入给定缓冲区?

    3 回复  |  直到 10 年前
        1
  •  18
  •   Community Mohan Dere    9 年前

    在对这个问题进行了更多的研究和对我的代码的仔细检查之后,我发现了 a post 建议使用手工编码 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);
        }
    };
    

    现在如果你看 my original code 你会发现我并不需要 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;
    }
    
        2
  •  4
  •   Éric Malenfant    17 年前

    看起来像的工作(正式否决,但仍然是标准) std::strstream .你也可以看看 Boost.IOStreams 图书馆, array_sink 尤其是。

        3
  •  1
  •   Clifford    17 年前

    正如您发布的链接所说:“具体的实现可能会有所不同”。

    不能简单地返回std::string对象,然后在需要char缓冲区的地方使用std::string::c_str()或std::string::data()?

    或者从C库中使用sprintf(),然后可以在传递的缓冲区中完成整个操作。由于这种方式可能导致潜在的缓冲区溢出,并且您使用VisualC++,您可能会考虑 sprintf_s