在c ++中以二进制文件存储可变大小结构的向量

时间:2016-05-11 20:46:03

标签: c++ vector struct binary

我正在尝试读取结构的向量并将其写入文件。迭代每个结构,首先我写下面结构的大小,然后我写结构。我在阅读文件时遇到崩溃。

结构:

struct Book {

   string author;
   string title;
   string isbn;
   int copies;
   Status status;

};

从文件加载:

void load_books(vector<Book> *books) {
ifstream readFile;
int read_size;
Book temp;

readFile.open(BOOK_DB_FILE.c_str(), ios::in | ios::binary) ;

while(readFile.read(reinterpret_cast<char*> (&read_size), sizeof(read_size))) {
    cout << read_size << endl;

    if (!readFile.read(reinterpret_cast<char*> (&temp), read_size)) {
        cout << "Failed to read library.dat!" << endl;
    }

    cout << "Attempting to load book..." << endl;
    cout << temp.title << ":" << temp.copies << endl;

    (*books).push_back(temp);

}
cout << "Loaded books!" << endl;

}

写入档案:

void save_books(vector<Book> *books) {
ofstream writeFile;
int write_size;

writeFile.open(BOOK_DB_FILE.c_str(), ios::out | ios::binary);

for (int ind = 0 ; ind < (*books).size(); ind++) {
    Book book = (*books)[ind];
    write_size = sizeof(book);

    cout << "Writing book with size: " << write_size << endl;
    cout << book.copies << " of " << book.title << " by " << book.author << endl;

    writeFile.write(reinterpret_cast<char*>(&write_size), sizeof(write_size));
    writeFile.write(reinterpret_cast<char*>(books + ind), write_size);
}

}

1 个答案:

答案 0 :(得分:1)

一般情况下,我总是建议使用像Boost.Serialization这样的库,但是,我不允许你使用Boost(或其他任何序列化库)。所以我们会看看你当前的方法。

虽然您将二进制对象布局直接转储到磁盘的方法充满了风险(例如,由于平台依赖性,如字节顺序),但我认为对于纯粹的类项目,我们可以忍受这些缺陷。

现在,您的主要问题是您正在将struct Book内存表示转储到磁盘并重新读取,但您忽略了std::string字段未处理的事实

在内部,std::string 不是POD ,而是(大致)另一个为实际字符串数据分配单独内存的类(为了便于说明,假设它在其实现中携带char*指针。您目前没有存储此数据;你只存储std::string内部指针的值,并在加载时读回它们。那时,这些内部指针指向无处有意义。

为了大致了解您需要做什么,您必须以递归方式显式地和单独地序列化/反序列化Book类的所有成员。大概是这样的:

  1. 存储author
  2. 的长度和原始字符串数据
  3. 存储title
  4. 的长度和原始字符串数据
  5. 存储isbn
  6. 的长度和原始字符串数据
  7. 存储整数copies
  8. 存储status
  9. 的枚举值

    阅读时,以同样的方式加载每个成员。因此,对于每个“基本”类型(在您的情况下,std::stringintStatus),以及“{”组合“序列化器和反序列化器函数”,您需要一个串行器/解串器函数{{ 1}}依次调用基本成员的序列化/反序列化函数。

    这也大致是Boost.Serialization在内部所做的,所以我建议你看看它无论如何。祝你好运!