2016-07-04 46 views
1

我需要使用从ASIO ::插座(带ASIO_STANDALONE)读取的数据作为一个IStreamASIO :: streambuf来的std :: 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”字符。 我试着用

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); 
} 

(正如我在这个问题efficient copy of data from boost::asio::streambuf to std::string看到的)但是,这会产生以下编译错误

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个副本(在缓冲区中,在字符串中和流)

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

回答

2

这里有很多方法,但很难在不知道你打算如何使用istream的情况下提供很好的建议。

有关此代码的一件事是,您完全确定地知道在istream的末尾会有一个换行符。没有可以采取的代码路径不会导致这种情况(除了I/O错误,您会提前发现)。

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

显然你想避免缓冲区副本,如果可能的话。

但是,如果你想整个流缓冲拷贝到一个字符串,你可以试试这个:如果你正在寻找解析字符串

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 
} 
+0

+1会与有关的IStream使用忽略空格样品额外的努力。荣誉提及真棒新颖''引用'当然:) :) – sehe

+0

缓冲区保证以新行结束。我将使用istream来解析它,但部分验证是在解析结束时istream是空的(只有''和'\ t'被接受为尾随字符),所以我需要删除新队。 –

+0

@sehe我有一种感觉,下一个问题将是关于高效的解析与精神......对你:) –

1

缓冲区迭代器假定你没有使用streambuf。如果你能接收到一个完全有效的缓冲区(序列)。

然而,你也许可以只使用

  1. 流缓冲迭代器:

    std::string line; 
    // Ignore the last char ('\n') 
    std::copy_n(std::istreambuf_iterator<char>(&buffer), bytes_transferred - 1, back_inserter(line)); 
    

    Live On Coliru

  2. iostream的空白感知功能(如std::getlinestd::skipws,这是默认启用)。

相关问题