我最近使用了boost asio,我发现我正在使用std::string
和asio::streambuf
s。我发现作为解析网络数据的一部分,我试图在streambuf
和string
之间来回传递数据。一般来说,我不想乱用'格式化的io',所以iostream
s不是很有用。我发现虽然ostream::operator<<()
尽管有官方文档,但似乎将我的string
转发到streambuf
s unmlested,istream::operator>>()
修改了我streambuf
的内容1}} s(正如你所期望的那样'格式')。
在我看来,标准库似乎缺少大量的迭代器和流对象来处理streambuf
和string
以及未格式化的io。例如,如果我想将string
的子字符串转换为streambuf
,如何在不创建string
副本的情况下执行此操作?基本的全能转移可以完成如下:
// Get a whole string into a streambuf, and then get the whole streambuf back
// into another string
{
boost::asio::streambuf sbuf;
iostream os(&sbuf);
string message("abcdefghijk lmnopqrs tuvwxyz");
cout << "message=" << message << endl;
os << message;
std::istreambuf_iterator<char> sbit(&sbuf);
std::istreambuf_iterator<char> end;
std::string sbuf_it_wholestr(sbit, end);
cout << "sbuf_it_wholestr=" << sbuf_it_wholestr << endl;
}
打印:
message=abcdefghijk lmnopqrs tuvwxyz
sbuf_it_wholestr=abcdefghijk lmnopqrs tuvwxyz
如果我想将streambuf
的一部分放入字符串中,那看起来真的很难,因为istreambuf_iterator
不是随机访问迭代器而且不支持算术:
// Get a whole string into a streambuf, and then get part of the streambuf back
// into another string. We can't do this because istreambuf_iterator isn't a
// random access iterator!
{
boost::asio::streambuf sbuf;
iostream os(&sbuf);
string message("abcdefghijk lmnopqrs tuvwxyz");
cout << "message=" << message << endl;
os << message;
std::istreambuf_iterator<char> sbit(&sbuf);
// This doesn't work
//std::istreambuf_iterator<char> end = sbit + 7; // Not random access!
//std::string sbuf_it_partstr(sbit, end);
//cout << "sbuf_it_partstr=" << sbuf_it_partstr << endl;
}
似乎没有任何方法直接使用string::iterator
将string
的一部分转储到streambuf
:
// istreambuf_iterator doesn't work in std::copy either
{
boost::asio::streambuf sbuf;
iostream os(&sbuf);
string message("abcdefghijk lmnopqrs tuvwxyz");
cout << "message=" << message << endl;
std::istreambuf_iterator<char> sbit(&sbuf);
//std::copy(message.begin(), message.begin()+7, sbit); // Doesn't work here
}
如果我不介意格式化的io,我可以随时从string
中取出streambuf
部分,但我这样做 - 格式化的io几乎不是我想要的:
// Get a whole string into a streambuf, and then pull it out using an ostream
// using formatted output
{
boost::asio::streambuf sbuf;
iostream os(&sbuf);
string message("abcdefghijk lmnopqrs tuvwxyz");
cout << "message=" << message << endl;
string part1, part2;
os << message;
os >> part1;
os >> part2;
cout << "part1=" << part1 << endl;
cout << "part2=" << part2 << endl;
}
打印:
message=abcdefghijk lmnopqrs tuvwxyz
part1=abcdefghijk
part2=lmnopqrs
如果我对丑陋的副本感到满意,我可以生成子字符串,当然 - std::string::iterator
是随机访问...
// Get a partial string into a streambuf, and then pull it out using an
// istreambuf_iterator
{
boost::asio::streambuf sbuf;
iostream os(&sbuf);
string message("abcdefghijk lmnopqrs tuvwxyz");
cout << "message=" << message << endl;
string part_message(message.begin(), message.begin()+7);
os << part_message;
cout << "part_message=" << part_message << endl;
std::istreambuf_iterator<char> sbit(&sbuf);
std::istreambuf_iterator<char> end;
std::string sbuf_it_wholestr(sbit, end);
cout << "sbuf_it_wholestr=" << sbuf_it_wholestr << endl;
}
打印:
message=abcdefghijk lmnopqrs tuvwxyz
part_message=abcdefg
sbuf_it_wholestr=abcdefg
stdlib还有一个奇怪的独立std::getline()
,它允许你从ostream
中提取个别行:
// If getting lines at a time was what I wanted, that can be accomplished too...
{
boost::asio::streambuf sbuf;
iostream os(&sbuf);
string message("abcdefghijk lmnopqrs tuvwxyz\n1234 5678\n");
cout << "message=" << message << endl;
os << message;
string line1, line2;
std::getline(os, line1);
std::getline(os, line2);
cout << "line1=" << line1 << endl;
cout << "line2=" << line2 << endl;
}
打印: message = abcdefghijk lmnopqrs tuvwxyz 1234 5678
line1=abcdefghijk lmnopqrs tuvwxyz
line2=1234 5678
我觉得我错过了一些Rosetta Stone,如果我发现它,处理std::string
和asio::streambuf
会更容易。应该放弃std::streambuf
界面并使用asio::mutable_buffer
,我可以从asio::streambuf::prepare()
中获取?
答案 0 :(得分:2)
istream :: operator&gt;&gt;()破坏了我的streambufs的内容(正如你所期望的那样'格式')。
使用std::ios::binary
标记打开输入流,并使用is >> std::noskipws
例如,如果我想将字符串的子字符串转换为streambuf,如何在不创建字符串副本的情况下执行此操作?可以像
一样完成基本的全进程传输
尝试
outstream.write(s.begin()+start, length);
或使用boost::string_ref
:
outstream << boost::string_ref(s).instr(start, length);
似乎没有任何方法直接使用string :: iterators将部分字符串转储为streambuf:
std::copy(it1, it2, ostreambuf_iterator<char>(os));
重新。解析消息行:
您可以使用iter_split
拆分为迭代器范围。
您可以使用boost::spirit::istream_iterator