c++ - asio::streambuf 到 std::istream 丢弃新行

标签 c++ c++11 boost-asio

我需要使用从 asio::socket(使用 ASIO_STANDALONE)读取的数据作为 istream

到目前为止我有这段代码

asio::error_code ec;
auto bytes_transferred = asio::read_until(socket, buffer, '\n', ec);

if(!ec)
{
    buffer.commit(bytes_transferred);
    std::istream line(&buffer);
    // use line
    buffer.consume(bytes_transferred);
}

我面临的问题是 '\n' 出现在 istream 的末尾,因为它没有被 read_until 丢弃。

声明是

tcp::socket socket;
asio::streambuf buffer;

所以我需要在构造流时忽略'\n'字符。 我试过(正如我在这个问题 efficient copy of data from boost::asio::streambuf to std::string 中看到的)

if(!ec)
{
    // Ignore the last char ('\n')
    std::string line = std::string(asio::buffers_begin(buffer),
                                   asio::buffers_begin(buffer) + bytes_transferred - 1);
    std::stringstream ss(line);
    // use line
    buffer.consume(bytes_transferred);
}

但这会产生以下编译错误

In instantiation of ‘struct asio::detail::buffers_iterator_types<asio::basic_streambuf<>, char>’:
lib/asio/asio/buffers_iterator.hpp:77:46:   required from ‘class asio::buffers_iterator<asio::basic_streambuf<>, char>’
file.h:58:78:   required from here
lib/asio/asio/buffers_iterator.hpp:60:5: error: no type named ‘value_type’ in ‘class asio::basic_streambuf<>’
     {
     ^
lib/asio/asio/buffers_iterator.hpp: In instantiation of ‘class asio::buffers_iterator<asio::basic_streambuf<>, char>’:
file.h:58:78:   required from here
lib/asio/asio/buffers_iterator.hpp:455:43: error: no type named ‘const_iterator’ in ‘class asio::basic_streambuf<>’
   typename BufferSequence::const_iterator begin_;

和其他一些人总是提示缺少类型。 我是 C++ 的新手,这条消息对我来说有点神秘,而且我不确定这是最好的方法,因为我将拥有相同数据的 3 个拷贝(在缓冲区、字符串和流)

什么可能是解决我的问题的方法?

最佳答案

这里有很多方法,但是如果不了解您打算如何使用 istream,就很难给出好的建议。

关于此代码的一件事是您绝对确定 istream 末尾会有一个换行符。没有任何可以采用的代码路径不会导致这种情况(除了 I/O 错误,您会及早发现)。

因此,很容易编写期望 \n 存在并忽略它的代码。

显然,如果可能,您希望避免缓冲区复制。

但是,如果你想将整个 streambuf 复制到一个字符串中,你可以试试这个:

auto buf = buffer.data(); /* where buffer is your asio::streambuf */
auto s = std::string(boost::asio::buffer_cast<const char*>(buf), 
                     boost::asio::buffer_size(buf) - 1); /* remove the newline */

当然,如果您希望从 istream 中解析字符串、数字等,那么末尾有一个换行符这一事实并不重要——它只是默认情况下被忽略的空格。

这个小程序展示了这一点:

#include <boost/asio.hpp>
#include <sstream>
#include <iomanip>
#include <iostream>


int main()
{
    std::ostringstream oss;

    oss << 10 << std::quoted("Hello\" World") << '\n';
    auto payload = oss.str();

    boost::asio::streambuf sb;
    std::ostream otmp(&sb);
    otmp.write(payload.data(), payload.size());

    // streambuf now contains string with newline

    std::string s;
    int i;
    std::istream itmp(&sb);
    itmp >> i >> std::quoted(s);

    std::cout << i << std::endl;   // expect 10
    std::cout << s << std::endl;   // expect Hello" World
}

关于c++ - asio::streambuf 到 std::istream 丢弃新行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38193105/

相关文章:

c++ - 虚函数输出奇怪的值

c++ - 将 ofstream 分配给 ostream

c++ - 从 LLVM 生成二进制文件

c++ - 双重检查锁定 : Fences and atomics

c++ - 使用 Boost Asio 异步等待文件描述符

c++ - std::map 的所有迭代器的模板特化

c++ - 不同命名空间中别名声明的成员特化

c++ - 如果在初始化静态局部变量之前发生异常会怎样?

networking - 为 IPv6 找到正确的 "network interface"号码

c++ - boost asio - 编写等效的代码