I'd like to copy a fixed length of data from an std::istream to a string:
std::istream & operator >> ( std::istream & is, LogMsg & msg )
{
// read in 4 bytes - a uint32_t that describes the number of bytes in message:
// next, read the message bytes into the LogMsg
typedef std::istream_iterator<unsigned char> Iter;
Iter i (is);
uint32_t nSize = 0;
std::string & sMsg = msg.MsgRef();
is >> nSize;
sMsg.reserve(nSize);
std::copy(
i.begin(), i.begin() + nSize,
std::back_inserter(sMsg)
);
return is;
}
I can't use this solution, as the std::istream_iterator::begin() function on the iterator is c++11 only (I'm constrained to -std=gnu++0x with gcc 4.4.7
So, how can I copy a fixed length of data from an input stream into a string?
I originally loooked at std::istream::read, which seems to fit - it has the following syntax
is.read (buffer,length);
But I don't think you can read into the internal buffers of a string and I'd like to avoid a copy to a temporary buffer. Can I use a streambuf somehow?
The obvious solution is std::copy_n:
std::copy_n( std::istreambuf_iterator<char>( is ), size, std::back_inserter( msg ) );
This will only work if you can be sure that the characters are there, however. If you encounter end of file while trying to read the characters, undefined behavior ensues. Which means that although it is an obvious solution, it maybe isn't a good one.
However, in C++11, officially, and in earlier implementations, in practice, you can read into the internal buffer. You must make sure that the string has enough space:
msg.resize( size );
is.read( &msg[0], msg.size() );
(For some reason, there isn't a non-const version of
std::string::data(), despite the guarantee of underlying contiguity in
C++11.)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With