Search code examples
c++istreamarraysnull-character

How to create C++ istringstream from a char array with null(0) characters?


I have a char array which contains null characters at random locations. I tried to create an iStringStream using this array (encodedData_arr) as below,

I use this iStringStream to insert binary data(imagedata of Iplimage) to a MySQL database blob field(using MySQL Connector/C++'s setBlob(istream *is) ) it only stores the characters upto the first null character.

Is there a way to create an iStringStream using a char array with null characters?

unsigned char *encodedData_arr = new unsigned char[data_vector_uchar->size()];
// Assign the data of vector<unsigned char> to the encodedData_arr
for (int i = 0; i < vec_size; ++i)
{
 cout<< data_vector_uchar->at(i)<< " : "<< encodedData_arr[i]<<endl;
}

// Here the content of the encodedData_arr is same as the data_vector_uchar
// So char array is initializing fine.
istream *is = new istringstream((char*)encodedData_arr, istringstream::in || istringstream::binary);

prepStmt_insertImage->setBlob(1, is);
// Here only part of the data is stored in the database blob field (Upto the first null character)

Solution

  • There is nothing special about null characters in strings

    std::istringstream iss(std::string(data, N));
    setBlob(&iss);
    

    Of course if you do

    std::istringstream iss("haha a null: \0");
    

    It will interpret that as a C-style string converted to std::string, and thus will stop at the \0, not taking it as a real content byte. Telling std::string the size explicitly allows it to consume any null byte as real content data.

    If you want to read directly from a char array, you can use strstream

    std::istrstream iss(data, N);
    

    That will directly read from the data provided by data, up to N bytes. strstream is declared "deprecated" officially, but it's still going to be in C++0x, so you can use it. Or you create your own streambuf, if you really need to read from a raw char* like that.

    struct myrawr : std::streambuf {
      myrawr(char const *s, size_t n) { 
        setg(const_cast<char*>(s), 
             const_cast<char*>(s), 
             const_cast<char*>(s + n));
      }
    };
    
    struct hasb { 
      hasb(char const *s, size_t n)
       :m(s, n)
      { }
      myrawr m;
    };
    
    // using base-from-member idiom
    struct myrawrs : private hasb, std::istream {
      myrawrs(char const *s, size_t n)
        :hasb(s, n), 
         std::istream(&static_cast<hasb*>(this)->m)
      { }
    };