4

I have stringstream object. It is filled through

stringstream ss;
boost::iostreams::copy(inp,ss);

from

boost::iostreams::filtering_streambuf<boost::iostreams::input> inp;

and actually holds ungzipped file within.

Now if i flush stringstream content to file with

std::ofstream ofs(path_to_file,std::ios_base::out|std::ios_base::binary);
ofs << ss.rdbuf();

everything is ok. File is filled with complete correct data.

But if i instead of flushing to file construct string like this

std::string s = ss.str();

content is truncated somewhere in the middle. It is not a persistent error, and it obviously depends on content of string buffer.

The content is HTML file in several languages.

What can it be? Thanks.

Alexander
  • 779
  • 8
  • 17

2 Answers2

6

How are you determining that the content is truncated? A stringstream can contain null characters and std::string s = ss.str() will copy those null characters and the characters after it to the std::string object.

However, if you then use functions that treat the std::string object's contents as a C style string, it will appear truncated:

#include <sstream>
#include <string>
#include <iostream>
#include <ostream>
#include <string.h>

using namespace std;

stringstream ss;

int main()
{
    ss << 'a' << 'b' << 'c' << (char) '\0' << '1' << '2' << '3';

    string s = ss.str();

    cout << s.size() << endl;
    cout << s.c_str() << " C string length: " << strlen(s.c_str()) << endl;
    cout << s << endl;
}

produces the following output:

7
abc C string length: 3
abc 123
Michael Burr
  • 333,147
  • 50
  • 533
  • 760
  • Michael, the cast to `char` of `'\0'` is unnecessary - it's already a character literal. Also worth noting in output on a terminal - there's no visible separation of "abc123". However, if you redirect the output to a file, you'll see the null in a hex dump. (Still got my upvote). – Nathan Ernst May 16 '13 at 19:52
  • I can see in debugger, that string is definitely truncated. – Alexander May 17 '13 at 07:09
  • If you're using the VS debugger, the basic string display is probably lying to you - the debugger display of `std::string` (and, as an FYI, of .NET string objects) will stop at a null character even if the object contains more data. Try stepping through my example program - the debugger displays "abc" for the value of `s`, even though `s.size()` and the last line of the program clearly indicate there is more. Also, you can expand the display (click the '+' next to the variable name in the debugger display) and it will list each element of the string - including the null characters. – Michael Burr May 17 '13 at 07:26
  • Yes you were right, actual string is complete, debugger displays incorrectly. – Alexander May 17 '13 at 09:36
  • I'm a little surprised that this debugger 'quirk' hasn't been fixed. I guess not a lot of people run into it, so there aren't a lot of complaints. But when you go get hit by it, it can really throw your debugging session into the weeds. – Michael Burr May 17 '13 at 21:41
3

It seems like you have null character symbol '\0' in your file. That considered as end of string.

Nikolay Viskov
  • 1,016
  • 6
  • 9
  • 1
    This is not correct: `std::string` is not null-terminated. Yes, it's true that the very last character is null (for C compatibility), but it allows for embedded nulls. `strlen(s.c_str())` is not necessarily the same as `s.size()`. – Nathan Ernst May 16 '13 at 19:48
  • agree, std::string is not, but C-string is a null-terminated sequence of characters – Nikolay Viskov May 16 '13 at 20:00