设置标准流使用的内部缓冲区(pubsetbuf) [英] Setting the internal buffer used by a standard stream (pubsetbuf)

查看:1311
本文介绍了设置标准流使用的内部缓冲区(pubsetbuf)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在编写一个需要将数据写入现有缓冲区的子例程,我想使用 stringstream 类,以方便数据的格式化。



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

  #include< sstream> 
#include< algorithm>

void FillBuffer(char * buffer,unsigned int size)
{
std :: stringstream message;
message<< Hello<< std :: endl;
message<< 世界! << 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<< 世界! << std :: endl;不幸的是,这并不适用于Visual C ++标准库下的C ++标准库实现,因为它不支持Visual C# Studio 2008; buffer 保持不变。



我看过 pubsetbuf

  virtual _Myt * __ CLR_OR_THIS_CALL setbuf(_Elem *,streamsize)
{//向外部代理提供缓冲区(do nothing)
return(this);
}

这似乎是给定C ++标准库实现的限制。

解决方案

在对这个问题进行一些更多的研究后, ,并仔细检查了我的代码,我遇到了帖子,建议使用手动编码的 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)
{
//设置put指针是缓冲区的开始并记录它的长度。
setp(buffer,buffer + bufferLength);
}
};

现在,如果您查看我原来的代码,你会注意到我真的不需要一个 stringstream 开始。我真正需要的是一种方法,使用 IOStream 库和 std :: ostream 是一个更好的类型来解决这个问题。顺便说一下,我怀疑这是 array_sink 类型来自 Boost.IOStreams



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

  #include< ostream> 
#includeostreambuf.h//从上面包含ostreambuf结构体的文件。

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

messageStream<< Hello<< std :: endl;
messageStream<< 世界! << std :: endl;
}


I'm writing a subroutine that needs to write data to an existing buffer, and I would like to use the stringstream class to facilitate the formatting of the data.

Initially, I used the following code to copy the contents of the stream into the buffer, but would like to avoid this solution as it copies too much data.

#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);
}

This is when I discovered the streambuf::pubsetbuf() method and simply rewrote the above code as follows.

#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;
}

Unfortunately, this does not work under the C++ standard library implementation that ships with Visual Studio 2008; buffer remains unchanged.

I looked at the implementation of pubsetbuf and it turns out that it literally "does nothing".

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

This appears to be a limitation of the given C++ standard library implementation. What is the recommended way to configure a stream to write its contents to a given buffer?

解决方案

After some more research on this problem, and scrutiny of my code, I came across a post suggesting the use of a hand-coded std::streambuf class. The idea behind this code is to create a streambuf that initializes its internals to refer to the given buffer. The code is as follows.

#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);
    }
};

Now if you look at my original code, you will notice that I didn't really need a stringstream to begin with. All I really needed was a way to write to an external buffer using the IOStream library and std::ostream is a much better type to address this problem. Incidentally, I suspect this is how the array_sink type from Boost.IOStreams is implemented.

Here is the modified code that uses my ostreambuf type.

#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;
}

这篇关于设置标准流使用的内部缓冲区(pubsetbuf)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆