简体   繁体   中英

Serializing Struct of vectors of vector

I`m in a bit complicated situation here. I want to save a struct of vectors to a file and read it after some time. But the problem is with the reading. I dont know how i can fill al vectors into structure from the saved file.

 struct TDNATable{


        std::vector<String>GenomOne;
        std::vector<String>GenomeL;
        std::vector<String>GenomeER;
        std::vector<String>GenomeRET;
        std::vector<String>GenomeSEL;

    };

    std::vector<TDNATable> DnaTbl;



//PSEUDO CODE:
    //For example simple writing could be
    ofstream file("C:\\Users\\User11\\Desktop\\SNF_TBL.INI", ios::binary);
    file.write((char*)&DnaTbl, sizeof(DnaTbl));

//Problem comes with reading 
 // impl
    ifstream file("C:\\Users\\User11\\Desktop\\SNF_TBL.INI",
        std::ifstream::binary);

    // get pointer to associated buffer object
    std::filebuf* pbuf = file.rdbuf();

    // get file size using buffer's members
    std::size_t size = pbuf->pubseekoff(0, file.end, file.in);
    pbuf->pubseekpos(0, file.in);

    // allocate memory to contain file data
    char* buffer = new char[size];

    // get file data
    pbuf->sgetn(buffer, size);

    file.close();


for (int i = 0; i < SnfTbl.size(); i++) {

//Back inserter can be used only with 1D vector        
std::copy(buffer, buffer +sizeof(buffer),
            std::back_inserter(SnfTbl[i].GenomeL);

        std::copy(buffer, buffer +sizeof(buffer),
            std::back_inserter(SnfTbl[i].GenomeER));



    }

    RefreshDFSGrid();


    delete[]buffer;
    file.close();

I tried with boost/serialize but without sucsess.

Do you have any idea how can i save/load this ds in a elegant way? Thanks!

Boost could be an overkill for easy tasks. In my own code, I solved that problem with sorts of stream class. I did it that way:

  1. Declare abstract base class with virtual Read(buffer, byteCount) = 0 and virtual Write(buffer, byteCount) = 0 . In illustration below, IArchiveI and IArchiveO are such base classes.

  2. For builtin types, provide operator << and operator >> that simply calls Read() and Write() as appropriate.

  3. For library types such as vector / string / ..., provide non-member template operators built on base type operators (eg you no longer call raw Read / Write).

For instance, there's how I handle a vector:

template <class T>
IArchiveO& operator << (IArchiveO& a_Stream, const std::vector<T>& a_Vector)
{
    a_Stream << a_Vector.size();
    for (size_t i = 0; i < a_Vector.size(); i++)
    {
        a_Stream << a_Vector[i];
    }

    return a_Stream;
}

template <class T>
IArchiveI& operator >> (IArchiveI& a_Stream, std::vector<T>& a_Vector)
{
    a_Vector.clear();

    size_t contSize = 0;
    a_Stream >> contSize;

    a_Vector.resize(contSize);
    for (size_t i = 0; i < contSize; i++)
    {
        a_Stream >> a_Vector[i];
    }

    return a_Stream;
}

For non-library types of your own, provide operators the same way. For instance, here's how your code would look like:

IArchiveI& operator >> (IArchiveI& a_Stream, TDNATable& a_Value)
{
    a_Stream >> a_Value.GenomOne;
    a_Stream >> a_Value.GenomeL;
    a_Stream >> a_Value.GenomeER;
    a_Stream >> a_Value.GenomeRET;
    a_Stream >> a_Value.GenomeSEL;
    return a_Stream;
}
  1. Inherit from base classes and make classes that provide storage, for instance, reading/writing to file. You will only need to overload virtual Read(buffer, byteCount) and virtual Write(buffer, byteCount) .

  2. Finally, you construct an instance of storage class and serialize your entire array in one go (in this code, CFileArchiveO is inherited from IArchiveO, overloading Write()): CFileArchiveO ar(...); ar << DnaTbl; CFileArchiveO ar(...); ar << DnaTbl;

The trick is, when compiler has operators for each type, it automatically builds code for whatever nesting you have, even if it's a vector<vector<vector<string>>>

std::vector allocates memory when inserting data.

So

file.write((char*)&DnaTbl, sizeof(DnaTbl));

only saves the " metadata " of std::vector<TDnaTbl> and leaves out the data you inserted, which is stored somewhere else in memory. You would have to iterate over the vector and save the element count and the element-data manually.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM