【问题标题】:Writing data structure with vector members to binary file将具有向量成员的数据结构写入二进制文件
【发布时间】:2016-03-25 02:00:48
【问题描述】:

尝试编写包含向量成员的数据结构时,我注意到从缓冲区读回数据时向量成员不准确。

首先我用简单的值手动写出结构:(假设 POD 成员在这种情况下是准确的。)

void ObjFileImport::WriteGeometryFile(LPWSTR In_File){
BaseGeometry WriteTest;
WriteTest.VertexData = {
    XMFLOAT3(9.5, 6.7f, 9.3f),
    XMFLOAT3(3.5f, 6.7f, 9.3f),
    XMFLOAT3(3.5f, 6.7f, 9.3f) };
WriteTest.ColorData = { XMFLOAT4(3.5f, 6.7f, 9.3f, 5.6f) };
WriteTest.Update();

ofstream File;
File.open(In_File, ofstream::binary | ofstream::out);

if (File.is_open()){
    File.write((const char*)&WriteTest.Version, sizeof(float));

    File.write((const char*)&WriteTest.sz_Array[0], sizeof(size_t)*WriteTest.sz_BG_Mbr); 

    File.write((const char*)WriteTest.ColorData.data(),         sizeof(XMFLOAT4)*WriteTest.sz_ColorData);
    File.write((const char*)WriteTest.ImageData.data(),         sizeof(XMFLOAT4)*WriteTest.sz_ImageData);
    File.write((const char*)WriteTest.VertexData.data(),        sizeof(XMFLOAT3)*WriteTest.sz_VertexData);
    File.write((const char*)WriteTest.NormalData.data(),        sizeof(XMFLOAT3)*WriteTest.sz_NormalData);
    File.write((const char*)WriteTest.TextureCoordData.data(),  sizeof(XMFLOAT2)*WriteTest.sz_TextureCoordData);

    File.write((const char*)&WriteTest.IndexVertexData,         sizeof(UINT)*WriteTest.sz_IndexVertexData);
    File.write((const char*)&WriteTest.IndexTextureCoordData,   sizeof(UINT)*WriteTest.sz_IndexTextureCoordData);
    File.write((const char*)&WriteTest.IndexNormalData,         sizeof(UINT)*WriteTest.sz_IndexNormalData);
}
File.close();
}

这很好用...根据读取时显示的常规类型,如下所示:

void ObjFileImport::ReadGeometryFile(LPWSTR In_File){
int Sz_Base = sizeof(BaseGeometry);
BaseGeometry Temp;
ifstream File;
File.open(In_File, ifstream::binary | ifstream::in | ifstream::ate);

if (File.is_open()){ 
    int FileSize = File.tellg();
    File.seekg(0, File.beg);

    //Read version number.
    File.read((char*)&Temp.Version, sizeof(float));

    File.read((char*)&Temp.sz_Array, sizeof(size_t)           *Temp.sz_BG_Mbr); //Test for heap tranfer

    File.read((char*)&Temp.ColorData, sizeof(XMFLOAT4)        *Temp.sz_ColorData);
    File.read((char*)&Temp.ImageData, sizeof(XMFLOAT4)        *Temp.sz_ImageData);
    File.read((char*)&Temp.VertexData, sizeof(XMFLOAT3)       *Temp.sz_VertexData);
    File.read((char*)&Temp.NormalData, sizeof(XMFLOAT3)       *Temp.sz_NormalData);
    File.read((char*)&Temp.TextureCoordData, sizeof(XMFLOAT2) *Temp.sz_TextureCoordData);

    File.read((char*)&Temp.IndexVertexData, sizeof(UINT)      *Temp.sz_IndexVertexData);
    File.read((char*)&Temp.IndexTextureCoordData, sizeof(UINT)*Temp.sz_IndexTextureCoordData);
    File.read((char*)&Temp.IndexNormalData, sizeof(UINT)      *Temp.sz_IndexNormalData);

    File.close();
}
}

不幸的是,在从数据缓冲区读取时,向量值(和大小)没有显示出来。

我知道向量本质上指向存储在堆上的数据,并试图获取该数据的内部指针WriteTest.data() 以读入二进制文件。读出后,数据似乎没有直观的结构。

【问题讨论】:

  • 就像你说的,一个向量包含一个指向堆分配数据的指针,并且所有堆分配(实际上是所有指针)对于当前进程都是唯一的.如果您保存指向已分配数据的指针,然后在另一个程序(甚至是同一个程序但作为新进程)中读取它,则该指针不再指向已分配的内存。您应该搜索并阅读有关serialization 的信息。有许多很好的库可以为您处理序列化,请使用它们。
  • 如果所有这些东西都是一个 std::vector,为什么会有单独的变量来指示每个向量的大小?你知道 std::vecto::size() 吗?而且,在读回数据时,“File.read((char*)&Temp.ColorData”会完全覆盖std::vector 本身,而不是data(),这也是你的责任,阅读时,在将数据读入 std::vector 的 data() 之前,调整 std::vector 的大小,使其包含足够的元素。
  • 有没有办法直接引用堆数据——复制到文件中?
  • 有没有办法直接引用堆数据 - 复制到文件中? 不,当它包含指针时,你不能这样做。此外,堆不必是连续的,您放在堆上的对象也不必按任何特定顺序排列。所以你会拿回垃圾。
  • 可以通过&v[0]stackoverflow.com/questions/6485496/…访问vector的行数据

标签: c++ vector data-structures fstream binaryfiles


【解决方案1】:

C++ STL 不提供将 STL 对象存储到磁盘的本地接口。

您可以查看this thread 寻求帮助。

【讨论】:

    【解决方案2】:

    对于这个实现,(正如 Sam Varshavchik,cmets 所指出的)vector 对象被覆盖,[同样],vector 的内部指针指向的相关数据在被引用时返回一个断言错误,因为没有正确调整被强制输入的数据的大小。

    void ObjFileImport::ReadGeometryFile(LPWSTR In_File){
    int Sz_Base = sizeof(BaseGeometry);
    BaseGeometry Temp;
    ifstream File;
    File.open(In_File, ifstream::binary | ifstream::in | ifstream::ate);
    
    if (File.is_open()){ 
        int FileSize = File.tellg();
        File.seekg(0, File.beg);
    
        //Read version number.
        File.read((char*)&Temp.Version, sizeof(float));
    
        //Brace for horrible things later. Read size definition array.
        File.read((char*)&Temp.sz_Array, sizeof(size_t)*Temp.sz_BG_Mbr); 
    
        //If local pointer null, make not null, else, allocate space.
        if (Temp.sz_ColorData == 0)Temp.ColorData.resize(1);
        else Temp.ColorData.resize(Temp.sz_ColorData);
    
        if (Temp.sz_ImageData == 0)Temp.ImageData.resize(1);
        else Temp.ImageData.resize(Temp.sz_ImageData);
    
        if (Temp.sz_VertexData == 0)Temp.VertexData.resize(1);
        else Temp.VertexData.resize(Temp.sz_VertexData);
    
        if (Temp.sz_TextureCoordData == 0)Temp.TextureCoordData.resize(1);
        else Temp.TextureCoordData.resize(Temp.sz_TextureCoordData);
    
        if (Temp.sz_NormalData == 0)Temp.NormalData.resize(1);
        else Temp.NormalData.resize(Temp.sz_NormalData);
    
        if (Temp.sz_IndexVertexData == 0)Temp.IndexVertexData.resize(1);
        else Temp.IndexVertexData.resize(Temp.sz_IndexVertexData);
    
        if (Temp.sz_IndexTextureCoordData == 0)Temp.IndexTextureCoordData.resize(1);
        else Temp.IndexTextureCoordData.resize(Temp.sz_IndexTextureCoordData);
    
        if (Temp.sz_IndexNormalData == 0)Temp.IndexNormalData.resize(1);
        else Temp.IndexNormalData.resize(Temp.sz_IndexNormalData);
    
        //Read contents of buffer in.
        File.read((char*)Temp.ColorData.data(), sizeof(XMFLOAT4)          *Temp.sz_ColorData);       // *Temp.sz_ColorData);
        File.read((char*)Temp.ImageData.data(), sizeof(XMFLOAT4)          *Temp.sz_ImageData);
        File.read((char*)Temp.VertexData.data(), sizeof(XMFLOAT3)         *Temp.sz_VertexData);
        File.read((char*)Temp.NormalData.data(), sizeof(XMFLOAT3)         *Temp.sz_NormalData);
        File.read((char*)Temp.TextureCoordData.data(),   sizeof(XMFLOAT2) *Temp.sz_TextureCoordData);
    
        File.read((char*)Temp.IndexVertexData.data(),   sizeof(UINT)      *Temp.sz_IndexVertexData);
        File.read((char*)Temp.IndexTextureCoordData.data(),   sizeof(UINT)*Temp.sz_IndexTextureCoordData);
        File.read((char*)Temp.IndexNormalData.data(),    sizeof(UINT)     *Temp.sz_IndexNormalData);
    
        File.close();
    }
    }  
    

    “固定”代码,尽管数据是否跨机器类型“持续存在”可能存在疑问。

    【讨论】:

    • 把数据放在一个共同的字节序中可能会解决你的持久性问题,因为这是一个二进制文件。虽然这些函数不是标准 c++。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-05-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多