簡體   English   中英

如何在c ++中正確地將向量寫入二進制文件?

[英]how to correctly write vector to binary file in c++?

感謝Mats Petersson關於如何將矢量復制到數組的解釋,這看起來很有用。 這是代碼snipet:

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

using namespace std;

class Student
  {
    private:
    char m_name[30];
    int m_score;

    public:
    Student()
      {

      }
    Student(const Student& copy)
      {
           m_score = copy.m_score;   //wonder why i can use this statment as
           strncpy(m_name, copy.m_name, 30); //declare it private
      }
      Student(const char name[], const int &score)
      :m_score(score)
      {
           strncpy(m_name, name, 30);
      }
      void print() const
      {
           cout.setf(ios::left);
           cout.width(20);
           cout << m_name << " " << m_score << endl;
      }
      };


      int main()
      {
        vector<Student> student;
        student.push_back(Student("Alex",19));
        student.push_back(Student("Maria",20));
        student.push_back(Student("muhamed",20));
        student.push_back(Student("Jeniffer",20));
        student.push_back(Student("Alex",20));
        student.push_back(Student("Maria",21));
      {
      Student temp[student.size()];
      unsigned int counter;
      for(counter = 0; counter < student.size(); ++counter)
      {
        temp[counter] = student[counter];
      }

      ofstream fout("data.dat", ios::out | ios::binary);
      fout.write((char*) &temp, sizeof(temp));
      fout.close();
      }

      vector<Student> student2;
      ifstream fin("data.dat", ios::in | ios::binary);

      {
        fin.seekg(0, ifstream::end);
        int size = fin.tellg() / sizeof (Student);
        Student temp2[size];
        fin.seekg(0, ifstream::beg);
        fin.read((char*)&temp2, sizeof(temp2));
        int counter;
        for(counter = 0; counter <6; ++counter)
        {
        student2.push_back(temp2[counter]);
        }
        fin.close();
      }
      vector<Student>::iterator itr = student2.begin();
      while(itr != student2.end())
      {
        itr->print();
        ++itr;
      }
      return 0;
      }

但我客人這種方法會浪費大量內存並且很麻煩。 也許我會考慮用ocelot和其他建議寫一下先生。 謝謝大家的回答。

要將PODvector<T>存儲在文件中,您必須編寫向量的內容,而不是向量本身。 您可以使用&vector[0]訪問原始數據,第一個元素的地址(假設它包含至少一個元素)。 要獲取原始數據長度,請將向量中的元素數乘以一個元素的大小:

strm.write(reinterpret_cast<const char*>(&vec[0]), vec.size()*sizeof(T));

當您從文件中讀取向量時,同樣適用; 元素計數是總文件大小除以一個元素的大小(假設您只在文件中存儲一種類型的POD):

const size_t count = filesize / sizeof(T);
std::vector<T> vec(count);
strm.read(reinterpret_cast<char*>(&vec[0]), count*sizeof(T));

這僅適用於您可以根據文件大小計算元素數量(如果您只存儲一種類型的POD或所有向量包含相同數量的元素)。 如果具有不同長度的不同POD的向量,則必須在寫入原始數據之前將向量中的元素數寫入文件。

此外,當您在不同系統之間以二進制形式傳輸數字類型時,請注意字節順序

您正在寫入文件向量結構,而不是其數據緩沖區。 嘗試將更改寫入過程更改為

 ofstream fout("data.dat", ios::out | ios::binary);
 fout.write((char*)&student[0], student.size() * sizeof(Student));
 fout.close();

而不是從文件大小計算向量的大小,而是更好地寫入向量大小(對象的數量)之前。 在這種情況下,您可以將同一文件寫入其他數據。

 size_t size = student.size();
 fout.write((char*)&size, sizeof(size));

您可能無法以二進制(您正在進行的方式)編寫任何std::vector因為該模板包含內部指針,寫入和重新讀取它們毫無意義。

一些一般性建議:

  • 不要在二進制文件中寫入任何STL模板容器(如std::vectorstd::map ),它們肯定包含你真正不想寫的內部指針。 如果您確實需要編寫它們,請實現自己的編寫和讀取例程(例如,使用STL迭代器)。

  • 避免使用strcpy而不小心。 如果名稱超過30個字符,您的代碼將崩潰。 至少,使用strncpy(m_name, name, sizeof(m_name)); (但即便如此,對於30個字符的名稱也會很糟糕)。 實際上, m_name應該是std::string

  • 顯式序列化您的容器類(通過處理每個有意義的成員數據)。 您可以考慮使用JSON表示法(或者可能是YAML ,或者甚至是XML,我發現它太復雜,所以不建議)進行序列化。 它為您提供了一種文本轉儲格式,您可以使用標准編輯器(例如emacsgedit )輕松檢查。 你會發現許多序列化的免費庫,例如jsoncpp和許多其他庫。

  • 學會用g++ -Wall -g編譯並使用gdb調試器和valgrind內存泄漏檢測器; 還學習使用make並編寫Makefile -s。

  • 利用Linux是免費軟件,所以你可以查看它的源代碼(你可能想學習stdc ++實現,即使STL頭很復雜)。

對於函數read()和write(),您需要所謂的“普通舊數據”或“POD”。 這基本上意味着類或結構必須在它們內部沒有指針,並且沒有虛函數。 vector的實現肯定有指針 - 我不確定虛函數。

你必須編寫一個一次存儲一個學生的函數(或者將一堆學生翻譯成一個字節的數組[不是矢量]或者一些這樣的 - 但這更復雜)。

您無法將非POD數據(尤其是指針)寫入二進制文件的原因是,當您再次讀取數據時,幾乎可以肯定的是,內存布局與您編寫時相比已經發生了變化。 它有點像試圖停在商店的同一個停車位 - 當你下次出現時,其他人會從入口處停在第三個位置,所以你必須選擇另一個位置。 將編譯器分配的內存視為停車位,將學生信息視為汽車。

[從技術上講,在這種情況下,情況更糟 - 你的矢量實際上並不包含課堂內的學生,這就是你寫入文件的內容,所以你甚至沒有保存關於學生的信息,只是信息關於它們的位置(停車位的數量)]

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM