c++ - efficent way to save objects into binary files -


i've class consists of matrix of vectors: vector< myfeatvector<t> > m_vcells, outer vector represents matrix. each element in matrix vector (i extended stl vector class , named myfeatvector<t>).

i'm trying code efficient method store objects of class in binary files. now, require 3 nested loops:

foutput.write( reinterpret_cast<char*>( &(this->at(dy,dx,dz)) ), sizeof(t) );

where this->at(dy,dx,dz) retrieves dz element of vector @ position [dy,dx].

is there possibility store m_vcells private member without using loops? tried like: foutput.write(reinterpret_cast<char*>(&(this->m_vcells[0])), (this->m_vcells.size())*sizeof(cfeaturevector<t>)); seems not work correctly. can assume vectors in matrix have same size, although more general solution welcomed :-)

furthermore, following nested-loop implementation, storing objects of class in binary files seem require more physical space storing same objects in plain-text files. bit weird.

i trying follow suggestion under http://forum.allaboutcircuits.com/showthread.php?t=16465 couldn't arrive proper solution.

thanks!

below simplified example of serialization , unserialization methods.

template < typename t > bool myfeatmatrix<t>::writebinary( const string & ofile ){      ofstream foutput(ofile.c_str(), ios::out|ios::binary);     foutput.write(reinterpret_cast<char*>(&this->m_nheight), sizeof(int));     foutput.write(reinterpret_cast<char*>(&this->m_nwidth), sizeof(int));     foutput.write(reinterpret_cast<char*>(&this->m_ndepth), sizeof(int));      //foutput.write(reinterpret_cast<char*>(&(this->m_vcells[0])), nsze*sizeof(cfeaturevector<t>));     for(register int dy=0; dy < this->m_nheight; dy++){        for(register int dx=0; dx < this->m_nwidth; dx++){           for(register int dz=0; dz < this->m_ndepth; dz++){               foutput.write( reinterpret_cast<char*>( &(this->at(dy,dx,dz)) ), sizeof(t) );           }        }     }      foutput.close();     return true; } 

template < typename t > bool myfeatmatrix<t>::readbinary( const string & ifile ){      ifstream finput(ifile.c_str(), ios::in|ios::binary);      int nheight, nwidth, ndepth;     finput.read(reinterpret_cast<char*>(&nheight), sizeof(int));     finput.read(reinterpret_cast<char*>(&nwidth), sizeof(int));     finput.read(reinterpret_cast<char*>(&ndepth), sizeof(int));      this->resize(nheight, nwidth, ndepth);      for(register int dy=0; dy < this->m_nheight; dy++){         for(register int dx=0; dx < this->m_nwidth; dx++){             for(register int dz=0; dz < this->m_ndepth; dz++){                 finput.read( reinterpret_cast<char*>( &(this->at(dy,dx,dz)) ), sizeof(t) );             }         }     }     finput.close();     return true; } 

a efficient method store objects array (or contiguous space), blast buffer file. advantage disk platters don't have waste time ramping , writing can performed contiguously instead of in random locations.

if performance bottleneck, may want consider using multiple threads, 1 thread handle output. dump objects buffer, set flag, writing thread handle output, releaving main task perform more important tasks.

edit 1: serializing example
following code has not been compiled , illustrative purposes only.

#include <fstream> #include <algorithm>  using std::ofstream; using std::fill;  class binary_stream_interface {     virtual void    load_from_buffer(const unsigned char *& buf_ptr) = 0;     virtual size_t  size_on_stream(void) const = 0;     virtual void    store_to_buffer(unsigned char *& buf_ptr) const = 0; };  struct pet     : public binary_stream_interface,     max_name_length(32) {     std::string     name;     unsigned int    age;     const unsigned int  max_name_length;      void    load_from_buffer(const unsigned char *& buf_ptr)         {             age = *((unsigned int *) buf_ptr);             buf_ptr += sizeof(unsigned int);             name = std::string((char *) buf_ptr);             buf_ptr += max_name_length;             return;         }     size_t  size_on_stream(void) const     {         return sizeof(unsigned int) + max_name_length;     }     void    store_to_buffer(unsigned char *& buf_ptr) const     {         *((unsigned int *) buf_ptr) = age;         buf_ptr += sizeof(unsigned int);         std::fill(buf_ptr, 0, max_name_length);         strncpy((char *) buf_ptr, name.c_str(), max_name_length);         buf_ptr += max_name_length;         return;     } };   int main(void) {     pet dog;     dog.name = "fido";     dog.age = 5;     ofstream    data_file("pet_data.bin", std::ios::binary);      // determine size of buffer     size_t  buffer_size = dog.size_on_stream();      // allocate buffer     unsigned char * buffer = new unsigned char [buffer_size];     unsigned char * buf_ptr = buffer;      // write / store object buffer.     dog.store_to_buffer(buf_ptr);      // write buffer file / stream.     data_file.write((char *) buffer, buffer_size);      data_file.close();     delete [] buffer;     return 0; } 

edit 2: class vector of strings

class many_strings     : public binary_stream_interface {     enum {max_string_size = 32};      size_t    size_on_stream(void) const     {         return m_string_container.size() * max_string_size  // total size of strings.                + sizeof(size_t); // room quantity variable.     }      void      store_to_buffer(unsigned char *& buf_ptr) const     {         // treat vector<string> variable length field.         // store quantity of strings buffer,         //     followed content.         size_t string_quantity = m_string_container.size();         *((size_t *) buf_ptr) = string_quantity;         buf_ptr += sizeof(size_t);          (size_t = 0; < string_quantity; ++i)         {             // each string fixed length field.             // pad '\0' first, copy data.             std::fill((char *)buf_ptr, 0, max_string_size);             strncpy(buf_ptr, m_string_container[i].c_str(), max_string_size);             buf_ptr += max_string_size;         }     }     void load_from_buffer(const unsigned char *& buf_ptr)     {         // actual coding left exercise reader.         // psuedo code:         //     clear / empty string container.         //     load quantity variable.         //     increment buffer variable size of quantity variable.         //     each new string (up quantity read)         //        load temporary string buffer via buffer pointer.         //        push temporary string vector         //        increment buffer pointer max_string_size.         //      end-for      }      std::vector<std::string> m_string_container; }; 

Comments

Popular posts from this blog

c# - SharpSVN - How to get the previous revision? -

c++ - Is it possible to compile a VST on linux? -

url - Querystring manipulation of email Address in PHP -