设置标准流使用的内部缓冲区 (pubsetbuf)
我正在编写一个需要将数据写入现有缓冲区的子例程,我想使用 stringstream
类,方便数据的格式化.
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);
}
这是我发现 streambuf::pubsetbuf()
方法,简单地将上面的代码改写如下.
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;
}
不幸的是,这在 Visual Studio 2008 附带的 C++ 标准库实现下不起作用;buffer
保持不变.
Unfortunately, this does not work under the C++ standard library implementation that ships with Visual Studio 2008; buffer
remains unchanged.
我查看了 pubsetbuf
的实现,结果发现它实际上什么都不做".
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);
}
这似乎是给定 C++ 标准库实现的限制.配置流以将其内容写入给定缓冲区的推荐方法是什么?
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?
推荐答案
在对这个问题进行更多研究并仔细检查我的代码后,我遇到了 一篇帖子 建议使用手动编码std::streambuf
类.这段代码背后的想法是创建一个 streambuf
来初始化它的内部以引用给定的缓冲区.代码如下.
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);
}
};
现在,如果您查看我的原始代码,你会注意到我并不是真的需要一个 stringstream
开始.我真正需要的是一种使用 IOStream 库和std::ostream
是一种更好的寻址类型这个问题.顺便说一句,我怀疑这就是 array_sink 类型来自 Boost.IOStreams 已实施.
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.
这是使用我的 ostreambuf
类型的修改后的代码.
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;
}
相关文章