[英]How to get part of a std::string into a streambuf without copying?
I'm using boost asio a lot lately and I find that I'm working with std::string
s and asio::streambuf
s quite a bit. 我最近经常使用boost asio,发现使用了
std::string
和asio::streambuf
相当多。 I find that I'm trying to get data back and forth between streambuf
s and string
sa lot as part of parsing network data. 我发现我正在尝试在
streambuf
和string
之间来回获取数据,这是解析网络数据的一部分。 In general, I don't want to mess around with 'formatted io', so iostream
s aren't very useful. 通常,我不想弄乱“ formatted io”,所以
iostream
并不是很有用。 I've found that while ostream::operator<<()
, in spite of the official documentation, seems to relay my string
s into streambuf
s unmolested, istream::operator>>()
mangles the contents of my streambuf
s (as you would expect given that it's 'formatted'). 我发现,尽管有官方文档,
ostream::operator<<()
似乎streambuf
我的string
中继到streambuf
,但istream::operator>>()
破坏了我的streambuf
的内容(如您会期望它是“格式化的”)。
It really seems to me like the standard library is missing a whole lot of iterators and stream objects for dealing with streambuf
s and string
s and unformatted io. 在我看来,标准库确实缺少用于处理
streambuf
和string
以及未格式化io的大量迭代器和流对象。 For example, if I want to get a substring of a string
into a streambuf
, how do I do that without creating a copy of the string
? 例如,如果要将字符串的子
string
放入streambuf
,如何在不创建string
副本的情况下做到这一点? A basic all-in-all-out transfer can be accomplished like: 基本的全进全出传输可以像这样完成:
// 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;
}
prints: 打印:
message=abcdefghijk lmnopqrs tuvwxyz
sbuf_it_wholestr=abcdefghijk lmnopqrs tuvwxyz
If I want to get just part of a streambuf
into a string, that seems really hard, because istreambuf_iterator
isn't a random access iterator and doesn't support arithmetic: 如果我只想将
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;
}
And there doesn't seem to be any way of directly using string::iterator
s to dump part of a string
into a streambuf
: 而且似乎没有任何直接使用
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
}
I can always pull partial string
s out of a streambuf
if I don't mind formatted io, but I do - formatted io is almost never what I want: 如果我不介意格式化io,我总是可以从
streambuf
拉出部分string
s,但是我愿意-格式化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;
}
prints: 打印:
message=abcdefghijk lmnopqrs tuvwxyz
part1=abcdefghijk
part2=lmnopqrs
If I'm ok with an ugly copy, I can generate a substring, of course - std::string::iterator
is random access... 如果我可以接受一个丑陋的副本,那么我可以生成一个子字符串,当然
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;
}
prints: 打印:
message=abcdefghijk lmnopqrs tuvwxyz
part_message=abcdefg
sbuf_it_wholestr=abcdefg
The stdlib also has the curiously stand-alone std::getline()
, which lets you pull individual lines out of an ostream
: 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;
}
prints: message=abcdefghijk lmnopqrs tuvwxyz 1234 5678 打印:message = abcdefghijk lmnopqrs tuvwxyz 1234 5678
line1=abcdefghijk lmnopqrs tuvwxyz
line2=1234 5678
I feel like there's some Rosetta Stone that I've missed and that dealing with std::string
and asio::streambuf
would be so much easier if I discovered it. 我感觉好像有些罗塞塔石碑错过了,如果我发现了
std::string
和asio::streambuf
,处理起来会容易得多。 Should a just abandon the std::streambuf
interface and make use of asio::mutable_buffer
, which I can get out of asio::streambuf::prepare()
? 应该只是放弃
std::streambuf
接口并使用asio::mutable_buffer
,我可以退出asio::streambuf::prepare()
吗?
istream::operator>>() mangles the contents of my streambufs (as you would expect given that it's 'formatted').
istream :: operator >>()处理我的streambuf的内容(正如您所期望的那样,它是“格式化的”)。
Open your input stream with std::ios::binary
flag and manipulate it with is >> std::noskipws
使用
std::ios::binary
标志打开输入流,并使用is >> std::noskipws
For example, if I want to get a substring of a string into a streambuf, how do I do that without creating a copy of the string?
例如,如果要将字符串的子字符串放入流缓冲中,如何在不创建字符串副本的情况下做到这一点? A basic all-in-all-out transfer can be accomplished like
基本的全进全出传输可以像
Try like 尝试像
outstream.write(s.begin()+start, length);
Or use boost::string_ref
: 或使用
boost::string_ref
:
outstream << boost::string_ref(s).instr(start, length);
And there doesn't seem to be any way of directly using string::iterators to dump part of a string into a streambuf:
而且似乎没有任何直接使用string :: iterators将一部分字符串转储到streambuf中的方法:
std::copy(it1, it2, ostreambuf_iterator<char>(os));
Re. 回覆。 parsing the message lines:
解析消息行:
You can split into iterator ranges with iter_split
. 您可以使用
iter_split
拆分为迭代器范围。
You can parse an embedded grammar on the fly with boost::spirit::istream_iterator
您可以使用
boost::spirit::istream_iterator
即时解析嵌入式语法
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.