C++ 将流缓冲的内容复制到字符串

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/877652/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 17:45:53  来源:igfitidea点击:

Copy a streambuf's contents to a string

c++stringboostboost-asiostreambuf

提问by tstenner

Apparently boost::asio::async_readdoesn't like strings, as the only overload of boost::asio::bufferallows me to create const_buffers, so I'm stuck with reading everything into a streambuf.
Now I want to copy the contents of the streambuf into a string, but it apparently only supports writing to char* (sgetn()), creating an istream with the streambuf and using getline().

显然boost::asio::async_read不喜欢字符串,因为唯一的重载boost::asio::buffer允许我创建const_buffers,所以我坚持将所有内容读入流缓冲。
现在我想将 streambuf 的内容复制到一个字符串中,但它显然只支持写入 char* ( sgetn()),使用 streambuf 创建一个 istream 并使用getline().

Is there any other way to create a string with the streambufs contents without excessive copying?

有没有其他方法可以在不过度复制的情况下使用流缓冲内容创建字符串?

回答by Johannes Schaub - litb

I don't know whether it counts as "excessive copying", but you can use a stringstream:

我不知道这是否算作“过度复制”,但您可以使用字符串流:

std::ostringstream ss;
ss << someStreamBuf;
std::string s = ss.str();

Like, to read everything from stdin into a string, do

就像,要将 stdin 中的所有内容读入字符串,请执行以下操作

std::ostringstream ss;
ss << std::cin.rdbuf();
std::string s = ss.str();

Alternatively, you may also use a istreambuf_iterator. You will have to measure whether this or the above way is faster - i don't know.

或者,您也可以使用istreambuf_iterator. 您将不得不衡量这种或上述方式是否更快 - 我不知道。

std::string s((istreambuf_iterator<char>(someStreamBuf)), 
               istreambuf_iterator<char>());

Note that someStreamBufabove is meant to represent a streambuf*, so take its address as appropriate. Also note the additional parentheses around the first argument in the last example, so that it doesn't interpret it as a function declaration returning a string and taking an iterator and another function pointer ("most vexing parse").

请注意,someStreamBuf上面的意思是表示 a streambuf*,因此请酌情取其地址。还要注意最后一个示例中第一个参数周围的附加括号,以便它不会将其解释为返回字符串并采用迭代器和另一个函数指针(“最令人烦恼的解析”)的函数声明。

回答by Sean DeNigris

It's reallyburied in the docs...

真的被埋在文档中......

Given boost::asio::streambuf b, with size_t buf_size...

鉴于boost::asio::streambuf b,有size_t buf_size...

boost::asio::streambuf::const_buffers_type bufs = b.data();
std::string str(boost::asio::buffers_begin(bufs),
                boost::asio::buffers_begin(bufs) + buf_size);

回答by tstenner

Another possibility with boost::asio::streambufis to use boost::asio::buffer_cast<const char*>()in conjunction with boost::asio::streambuf::data()and boost::asio::streambuf::consume()like this:

另一种可能性boost::asio::streambuf是与这样boost::asio::buffer_cast<const char*>()结合使用:boost::asio::streambuf::data()boost::asio::streambuf::consume()

const char* header=boost::asio::buffer_cast<const char*>(readbuffer.data());
//Do stuff with header, maybe construct a std::string with std::string(header,header+length)
readbuffer.consume(length);

This won't work with normal streambufs and might be considered dirty, but it seems to be the fastest way of doing it.

这不适用于普通的流缓冲,并且可能被认为是脏的,但它似乎是最快的方法。

回答by iericzhou

For boost::asio::streambufyou may find a solution like this:

因为boost::asio::streambuf您可能会找到这样的解决方案:

    boost::asio::streambuf buf;
    /*put data into buf*/

    std::istream is(&buf);
    std::string line;
    std::getline(is, line);

Print out the string :

打印出字符串:

    std::cout << line << std::endl;

You may find here: http://www.boost.org/doc/libs/1_49_0/doc/html/boost_asio/reference/async_read_until/overload3.html

您可以在这里找到:http: //www.boost.org/doc/libs/1_49_0/doc/html/boost_asio/reference/async_read_until/overload3.html

回答by ArtemGr

One can also obtain the characters from asio::streambufusing std::basic_streambuf::sgetn:

还可以asio::streambuf使用std::basic_streambuf::sgetn以下方法获取字符:

asio::streambuf in;
// ...
char cbuf[in.size()+1]; int rc = in.sgetn (cbuf, sizeof cbuf); cbuf[rc] = 0;
std::string str (cbuf, rc);

回答by user121826

The reason you can only create const_buffer from std::string is because std::string explicitly doesn't support direct pointer-based writing in its contract. You could do something evil like resize your string to a certain size, then const_cast the constness from c_str() and treat it like a raw char* buffer, but that's very naughty and will get you in trouble someday.

您只能从 std::string 创建 const_buffer 的原因是因为 std::string 在其合同中明确不支持直接基于指针的写入。您可以做一些邪恶的事情,例如将字符串调整为特定大小,然后从 c_str() 中 const_cast 常量并将其视为原始 char* 缓冲区,但这非常顽皮,总有一天会给您带来麻烦。

I use std::vector for my buffers because as long as the vector doesn't resize (or you are careful to deal with resizing), you can do direct pointer writing just fine. If I need some of the data as a std::string, I have to copy it out, but the way I deal with my read buffers, anything that needs to last beyond the read callback needs to be copied out regardless.

我将 std::vector 用于我的缓冲区,因为只要向量不调整大小(或者您小心处理调整大小),您就可以直接写入指针。如果我需要一些数据作为 std::string,我必须将它复制出来,但是我处理我的读取缓冲区的方式,任何需要在读取回调之后持续的东西都需要被复制出来。

回答by DevMac

A simpler answer would be to convert it in std::stringand manipulate it some what like this

一个更简单的答案是将其转换std::string并像这样操作它

 std::string buffer_to_string(const boost::asio::streambuf &buffer)
 {
  using boost::asio::buffers_begin;
  auto bufs = buffer.data();
  std::string result(buffers_begin(bufs), buffers_begin(bufs) + buffer.size());
 return result;
}

Giving a very concise code for the task.

为任务提供非常简洁的代码。

回答by tstenner

I mostly don't like answers that say "You don't want X, you want Y instead and here's how to do Y" but in this instance I'm pretty sure I know what tstenner wanted.

我大多不喜欢这样的答案:“你不想要 X,你想要 Y,这里是如何做 Y”,但在这种情况下,我很确定我知道 tstenner 想要什么。

In Boost 1.66, the dynamic string buffertype was added so async_readcan directly resize and write to a string buffer.

在 Boost 1.66 中,添加了动态字符串缓冲区类型,因此async_read可以直接调整大小并写入字符串缓冲区。

回答by Nikolai Fetissov

I think it's more like:

我觉得更像是:


streambuf.commit( number_of_bytes_read );

istream istr( &streambuf );
string s;
istr >> s;

I haven't looked into the basic_streambufcode, but I believe that should be just one copy into the string.

我没有研究过basic_streambuf代码,但我相信应该只是字符串中的一个副本。

回答by Nikolai Fetissov

I tested the first answer and got a compiler error when compiling using "g++ -std=c++11" What worked for me was:

我测试了第一个答案,并在使用“g++ -std=c++11”编译时遇到了编译器错误对我有用的是:

        #include <string>
        #include <boost/asio.hpp>
        #include <sstream>           
        //other code ...
        boost::asio::streambuf response;
        //more code
        std::ostringstream sline;
        sline << &response; //need '&' or you a compiler error
        std::string line = sline.str(); 

This compiled and ran.

这编译并运行。