如何正确书写载体,在C ++中的二进制文件?(how to correctly write vect

2019-07-17 16:57发布

由于MATS皮特森在解释如何对矢量复制到阵列,它似乎工作。 下面是一小段代码片段:

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

但我客人此方法将浪费大量的内存和很麻烦。 也许我会考虑和豹猫等建议写它先生。 感谢大家的答案。

Answer 1:

您写入文件的矢量结构,而不是它的数据缓冲。 尝试改变写作过程:

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


Answer 2:

要存储vector<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,或者如果所有载体含有相同数量的元素)。 如果你有不同长度的不同荚载体,你写的原始数据之前写的矢量文件元素的数量。

此外,当你在不同的系统之间的二进制形式传输,数字类型,应注意的字节顺序 。



Answer 3:

你可能无法以二进制写任何(你正在做的方式) 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头很复杂)。



Answer 4:

对于函数read()和write()方法,你需要的是所谓的“普通的旧数据”或“POD”。 这意味着基本上是类或结构必须具有在其内部没有指针,和没有虚函数。 向量执行肯定有指针 - 我不知道虚函数。

你必须写在某时刻存储一个学生的函数(或翻译一帮同学到字节数组[不]的载体或一些这样的 - 但是这更复杂)。

你不能写非POD数据,尤其是三分球,二进制文件的原因是,当你再次读取数据,就可以几乎肯定的赌注,内存布局已经从当你写的改变。 这就像试图在商店在同一个停车位停放一点点 - 别人会已经停在从当你下一次打开了入口的第三位,所以你必须选择另一个地方。 认为由编译器车位分配的内存,和学生信息汽车。

[技术上,在这种情况下,它甚至更糟 - 你的载体实际上并不包含类,这是你写的文件中的学生,所以你还没有保存的有关学生的信息,只是信息关于它们的位置(车位数)]



文章来源: how to correctly write vector to binary file in c++?
标签: c++ fstream