【问题标题】:Serializing Struct of vectors of vector序列化向量的向量结构
【发布时间】:2013-08-19 13:39:43
【问题描述】:

我在这里的情况有点复杂。 我想将向量结构保存到文件中并在一段时间后读取它。 但问题在于阅读。我不知道如何将所有向量从保存的文件中填充到结构中。

 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();

我尝试了 boost/serialize 但没有成功。

您知道如何以优雅的方式保存/加载此 ds 吗? 谢谢!

【问题讨论】:

标签: c++ serialization file-io


【解决方案1】:

对于简单的任务来说,Boost 可能是一种过度杀伤力。在我自己的代码中,我用各种流类解决了这个问题。我是这样做的:

  1. virtual Read(buffer, byteCount) = 0virtual Write(buffer, byteCount) = 0 声明抽象基类。在下图中,IArchiveIIArchiveO 就是这样的基类。

  2. 对于内置类型,请提供 operator &lt;&lt;operator &gt;&gt;,它们只需根据需要调用 Read() 和 Write()。

  3. 对于向量/字符串/...等库类型,提供基于基本类型运算符构建的非成员模板运算符(例如,您不再调用原始读/写)。

例如,我是如何处理向量的:

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;
}

对于您自己的非库类型,以相同方式提供运算符。 例如,您的代码如下所示:

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. 从基类继承并创建提供存储的类,例如,读取/写入文件。您只需要重载virtual Read(buffer, byteCount)virtual Write(buffer, byteCount)

  2. 最后,您构造了一个存储类的实例并一次性序列化整个数组(在此代码中,CFileArchiveO 继承自 IArchiveO,重载了 Write()): CFileArchiveO ar(...); ar << DnaTbl;

诀窍是,当编译器对每种类型都有运算符时,它自动为您拥有的任何嵌套构建代码,即使它是 vector&lt;vector&lt;vector&lt;string&gt;&gt;&gt;

【讨论】:

  • IArchiveI 和 IArchiveO 不是标准 C++ 类。是否应该修改此示例代码以使用标准 C++ 类型?
  • 这些是第 1 点中提到的基类。我更新了我的答案以澄清。
【解决方案2】:

std::vector 在插入数据时分配内存。

所以

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

仅保存std::vector&lt;TDnaTbl&gt; 的“元数据”,而忽略您插入的数据,这些数据存储在内存中的其他位置。您必须遍历向量并手动保存元素计数和元素数据。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-04-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-12-25
    • 2012-07-06
    • 1970-01-01
    • 2014-07-06
    相关资源
    最近更新 更多