设置标准流使用的内部缓冲区(pubsetbuf) [英] Setting the internal buffer used by a standard stream (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 $ c $
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屋!