I would use the std::istream.read function to just read raw bytes into a stack array (for speed) and then assign to the string.
std::ifstream f( "file.bin", std::ios::in | std::ios::binary); std::string result; // read len unsigned char sz; f.read( (char *) &sz, sizeof( sz)); // read data char s0[ 256]; f.read( s0, sz); result.assign( s0, s0 + sz);
By way of explanation, my first thought would be to use iterators after getting the length, eg
std::istream_iterator< char> start( f); std::copy( start, start + sz, std::back_inserter( result));
but
1) istream_iterator isnt a random access iterator to which you can add fix the offset bytes you want to read.
2) alternatively you could use std::copy_n to fix the distance but it seems to be depricated.
3) and even if file is opened ios::binary whitespace is ignored for istream_iterator so it would skip valuable data. [edit] you can use std::istreambuf_iterator< char> start( f); but its still not random access
My collegue says that pascal string lengths are always one byte encoded. If they aren't then maybe use an oversized stack array for small pascal strings and then do an allocation using std::vector if large, something like this,
unsigned sz; // if len was encoded using 32 bit integer f.read( (char *) &sz, sizeof( sz)); const unsigned small_sz = 256; if( sz < small_sz) { // if string is small then use stack buffer for speed char s0[ small_sz]; f.read( s0, sz); result.assign( s0, s0 + sz); } else { // otherwise allocate dynamic buffer then assign to string std::vector< char> s0( sz); f.read( &s0[ 0], s0.size()); result.assign( s0.begin(), s0.end()); }
note that you have to be careful with endiness issues
[Edited by - chairthrower on October 9, 2008 10:12:50 AM]