在c ++中写入/读取二进制文件的结构

时间:2012-05-07 15:55:52

标签: c++ serialization binary structure ifstream

我正在构建一个数据库工具,我想要做的就是将结构写入二进制文件,然后再次读取。以下是我在网上找到的最接近的内容,但它存在重大问题:

#include <fstream>
#include <iostream>
#include <vector>
#include <string.h>

using namespace std;


typedef struct student
{
    char name[10];
    int age;
    vector<int> grades;
}student_t;

int main()
{
    student_t apprentice[3];  
    strcpy(apprentice[0].name, "john");
    apprentice[0].age = 21;
    apprentice[0].grades.push_back(1);
    apprentice[0].grades.push_back(3);
    apprentice[0].grades.push_back(5);    

    strcpy(apprentice[1].name, "jerry");
    apprentice[1].age = 22;
    apprentice[1].grades.push_back(2);
    apprentice[1].grades.push_back(4);
    apprentice[1].grades.push_back(6);

    strcpy(apprentice[2].name, "jimmy");
    apprentice[2].age = 23;
    apprentice[2].grades.push_back(8);
    apprentice[2].grades.push_back(9);
    apprentice[2].grades.push_back(10);

    // Serializing struct to student.data
    ofstream output_file("students.data", ios::binary);
    output_file.write((char*)&apprentice, sizeof(apprentice));
    output_file.close();

    // Reading from it
    ifstream input_file("students.data", ios::binary);
    student_t master[3];
    input_file.read((char*)&master, sizeof(master));   

    apprentice[0].grades[0]=100; // ALTERING THE INPUT STRUCTURE AFTER WRITE

    for (size_t idx = 0; idx < 3; idx++)
    {
        // If you wanted to search for specific records, 
        // you should do it here! if (idx == 2) ...

        cout << "Record #" << idx << endl;
        cout << "Name: " << master[idx].name << endl;
        cout << "Age: " << master[idx].age << endl;
        cout << "Grades: " << endl;
        for (size_t i = 0; i < master[idx].grades.size(); i++)
           cout << master[idx].grades[i] << " ";
        cout << endl << endl;
    }

    return 0;
}

这似乎写了文件,读回来然后打印到屏幕但不幸的是:首先程序崩溃,调试断言失败(dbgdel.cpp第52行),当它试图关闭,其次,改变结构(如我在示例中所示)改变了所谓的读取结构。我想正在发生的事情是,“Data”和“inData”在某种程度上是相同的(它可以解释崩溃,因为它会尝试从内存中删除相同的东西两次)。谁能让这个工作吗?我已经尝试了我能想到的一切。

3 个答案:

答案 0 :(得分:0)

问题是你的结构是动态的(由于向量)。这总是会使事情变得复杂,因为你实际上存储了一个char *。向量是一种复杂的数据结构。你不能只把它掩盖为char *并期望它代表元素。所以你甚至没有存储你需要的东西。 我建议你将矢量改为int grades[NO_OF_SUBJECTS]。这应该可以正常工作。

答案 1 :(得分:0)

您需要知道的事情:

你对矢量的push_back不会增加sizeof(学徒)。 Vector没有在struct中线性嵌套,vector在内部分配内存。您可以将vector对象(以及许多其他STL容器对象)视为指针。

您需要使用常量大小的数组而不是vector。

或者,您可以将每个矢量组件转储到该文件中,并在读取它们时用push_back解析它们。

答案 2 :(得分:0)

正如其他人所指出的,vector更像是一个指针,因此sizeof将无效。你要么必须使用具有固定数量等级的静态C数组(sizeof 在那里工作),要么你必须通过写成绩来序列化等级数。 size()为每个学生提交,然后写每个年级。

然后当你回读你的时候:

  1. 读取名称
  2. 阅读年龄
  3. 阅读成绩数
  4. 知道要阅读多少年级,阅读每个年级并推回学生
  5. 你也可以允许变量大小的名字通过null终止和沿着读取字符进行调整直到你点击'\ 0',或者你可以序列化名称长度并按上面的方式阅读。

    这比你上面的内容更乏味。但是你为复杂性交换了灵活性。