Angus Comber
Angus Comber

Reputation: 9708

Stream processing errors with stream with embedded nulls

I have a function I need to use in a library which works with a stream. The actual input data is unsigned char buffer with embedded nulls and indeed each byte can be any character/integer from 0-255.

I have the source code to the library and can change it. Given a stream of bytes like this:

0x30, 0xb, 0x0, 0x6, 0x6

If I use a std::istringstream stream constructed from the char buffer, as soon as 0x0 is reached in the read_stream function, peek returns EOF???

When I try to copy the contents of the stream to a vector stream processing is stopping on reaching the null character. How can I fix this. I want to copy ALL the binary characters to the vector.

#include <vector>
#include <iostream>
#include <sstream>

static void read_stream(std::istream& strm, std::vector<char>& buf)
{
   while(strm) {
      int c (strm.peek());
      if(c != EOF) {    // for the 3rd byte in stream c == 0xffffffff (-1) (if using istrngstream)
         strm.get();
         buf.push_back(c);
      }
   }
}


int main() {
   char bin[] = {0x30, 0xb, 0x0, 0x6, 0x6, 0x2b, 0xc, 0x89, 0x36, 0x84, 0x13, 0xa, 0x1};
   std::istringstream strm(bin);
   std::vector<char> buf;
   read_stream(strm, buf);

   //works fine doing it this way
   std::ofstream strout("out.bin",std::ofstream::binary);
   strout.write(bin, sizeof(bin));
   strout.close();
   std::ifstream strmf("out.bin",std::ifstream::binary);
   std::vector<char> buf2;
   read_stream(strmf, buf2);


   return 0;
}

EDIT:

I realise now that an embeeded null has no special significance in a stream. So this issue must be something to do with istringstream.

Upvotes: 0

Views: 277

Answers (1)

Captain Obvlious
Captain Obvlious

Reputation: 20073

What you pass a C style string (char pointer) to the std::istringstream constructor it actually instantiates a std::string and passes that instead. This happens due to an implicit conversion. The conversion constructor of std::string interprets a null byte character in C style strings as an end of string terminator causing all characters after it to be ignored.

To avoid this you can explicitly construct a std::string specifying the size of the data and pass it to std::istringstream

char bin[] = {0x30, 0xb, 0x0, 0x6, 0x6, 0x2b, 0xc, 0x89, 0x36, 0x84, 0x13, 0xa, 0x1};
std::istringstream strm(std::string(bin, sizeof(bin) / sizeof(bin[0])));




Note: I don't know exactly what you are trying to accomplish but I recommend using std::vector instead of a raw character buffer if possible.

Upvotes: 0

Related Questions