我有一个ostream
,并且已经写入了数据。现在我想要char
数组形式的数据。有没有办法获取char缓冲区及其大小而不复制所有字节?我的意思是,我知道我可以使用ostringstream
并在其上调用str().c_str()
,但这会产生临时副本。
答案 0 :(得分:2)
我想这就是你要找的东西 - 一个流缓冲区,它返回一个指向缓冲区的指针:
#include <iostream>
#include <vector>
#include <string>
class raw_buffer : public std::streambuf
{
public:
raw_buffer(std::ostream& os, int buf_size = 256);
int_type overflow(int_type c) override;
std::streamsize showmanyc() override;
std::streamsize xsputn(const char_type*, std::streamsize) override;
int sync() override;
bool flush();
std::string const& str() const;
private:
std::ostream& os_;
std::vector<char> buffer;
std::string aux;
};
现在str()
很简单。它返回一个指向辅助缓冲区底层缓冲区的指针:
std::string const& raw_buffer::str() const
{
return aux;
}
其余的函数是流缓冲区的常用实现。 showmanyc()
应该返回辅助缓冲区的大小(aux
只是整个缓冲区的运行总和,另一方面buffer
是构造时指定的大小。)
例如,这里是overflow()
,它应该同时更新两个缓冲区,但仍将buffer
视为主缓冲区:
raw_buffer::int_type raw_buffer::overflow(raw_buffer::int_type c) override
{
if (os_ && !traits_type::eq_int_type(c, traits_type::eof()))
{
aux += *this->pptr() = traits_type::to_char_type(c);
this->pbump(1);
if (flush())
{
this->pbump(-(this->pptr() - this->pbase()));
this->setp(this->buffer.data(),
this->buffer.data() + this->buffer.size());
return c;
}
}
return traits_type::eof();
}
flush()
用于将buffer
的内容复制到流(os_
),并且应覆盖sync()
以调用flush()
。< / p>
xsputn
也需要被覆盖以写入aux
:
std::streamsize raw_buffer::xsputn(const raw_buffer::char_type* str, std::streamsize count) override
{
for (int i = 0; i < count; ++i)
{
if (traits_type::eq_int_type(this->sputc(str[i]), traits_type::eof()))
return i;
else
aux += str[i];
}
return count;
}
现在我们可以将它与自定义流一起放在一起:
class raw_ostream : private virtual raw_buffer
, public std::ostream
{
public:
raw_ostream(std::ostream& os) : raw_buffer(os)
, std::ostream(this)
{ }
std::string const& str() const
{
return this->raw_buffer::str();
}
std::streamsize count()
{
return this->str().size();
}
};
可以像这样使用:
int main()
{
raw_ostream rostr(std::cout);
rostr << "Hello, World " << 123 << true << false;
auto& buf = rostr.str();
std::cout << buf;
}