5

I was testing how to read data out of an std::streamstring but I'm getting it wrong, could anyone point out what's the problem? and give a correct way to read it?

My testing code is:

#include <iostream> #include <string> #include <sstream> #define BUFFER_SIZE 16 int main(int argc, char ** argv) { std::stringstream ss; ss << "Un texto con datos de ejemplo para probar la extacción de un stream"; std::cout << "Stream contents: '" << ss.str() << "'" << std::endl; char buffer[BUFFER_SIZE] = {0}; std::streamsize read = 0; do { read = ss.readsome(buffer, BUFFER_SIZE - 1); std::cout << "Read: " << ss.gcount() << std::endl; std::cout << buffer << std::endl; std::cout << "---" << std::endl; std::fill(buffer, buffer + BUFFER_SIZE, 0); } while ( read > 0 ); return 0; } 

And I'm getting the output:

Stream contents: 'Un texto con datos de ejemplo para probar la extacci¾n de un stream' Read: 15 Un texto con da --- Read: 15 tos de ejemplo --- Read: 15 para probar la --- Read: 15 extacci¾n de un --- Read: 5 stre --- Read: 0 --- 

As you may notice the last read operation reads only 5 characters leaving out the last two 'am' even though it should have been able to read it. Am I missing somtehing?

6
  • I think you need to work with wchar_t version of streams and strings. Commented May 12, 2015 at 7:08
  • 1
    Replacing the ó with a regular o result in the same result. Why would I need to work with wchar_t anyway? Commented May 12, 2015 at 7:13
  • 1
    I copied your code into a .cpp file and compiled using g++ with no arguments. On my machine, the entire stream gets printed with no truncation, but the first read only grabs one character. I'm using gcc 4.9.2, and glibc 2.21-3. Commented May 12, 2015 at 7:24
  • 2
    Regarding the comment from @BarryGackle, you can see it for your self here. Might be a bug in the VS2008 (which is quite old now) standard library. Commented May 12, 2015 at 7:28
  • 1
    Could be that a bug is present in one compiler and not the other. Could also be a bug in the code that, for whatever reason, happens to manifest itself differently on different compilers/machines (like you'd expect a buffer overflow to do). I'm leaning towards the first of those, since several people seem to have looked at your code and none of us has seen any obvious issues with it. You definitely aren't doing anything obviously wrong, though, or we'd all see the same result. Commented May 12, 2015 at 7:33

1 Answer 1

4

Actually, readsome does only read the immediately available characters and what that is depends on the platform, so it is well allowed to return 0 while there are still characters in the stream and a subsequent call could probably return the missing characters. To get all available data, I'd rather use read in combination with gcount to get the Number of characters you read.

do { ss.read(buffer, BUFFER_SIZE - 1); read=ss.gcount(); std::cout << "Read: " << ss.gcount() << std::endl; std::cout << buffer << std::endl; std::cout << "---" << std::endl; std::fill(buffer, buffer + BUFFER_SIZE, 0); } while ( read > 0 ); 

Just for clarification:
While I believe, the behavoir you observed is allowed by the standard, I don't see why the implementation should behave like this when the input stream is based on a string literal (im not familiar with the implementation details of streams). What you could check is, if read actually corresponds to rdbuf()->in_avail() and if it doesn't this might indeed be a compiler bug.

Sign up to request clarification or add additional context in comments.

3 Comments

Making that change solve the problem. So readsome should be used in a pooling manner? (since may return 0 event though there is content left).
@Javier Mr: I don't really know. As Far as I can tell, the Idea behind readsome is to give you all characters that are available without a potentially blocking systemcall. So I'm not sure If you'll get all the data at all. On the other hand I also don't understand, why the specific implementation of VC++2008 would not give you all the data from a local string object. If you are talking about thread pools however, I'd definitely say no as it is not threadsafe, so you would have to serialize it anyway.
yea I meant single threaded consecutive calls. I understand the aim of readsome to block as little as possible. However I tested changing the do-while condition to !ss.eof() and apparently readsome never reads the whole stream, also checked the in_avail and starts with a value of 50 and in each call decreases without ever reading the last ones. Thanks.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.