如何在C 中正确写入向量到二进制文件
how to correctly write vector to binary file in c++?
首先对我的英语不好。我刚加入这个论坛并搜索如何正确地将矢量写入二进制文件。我刚从这个论坛获得了这样的答案(我已经对其进行了一些修改):
#include <iostream>
#include <string.h>
#include <vector>
#include <fstream>
using namespace std;
class Student
{
public:
char m_name[30];
int m_score;
public:
Student()
{
}
Student(const char name[], const int &score)
:m_score(score)
{
strcpy(m_name, name);
}
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));
ofstream fout("data.dat", ios::out | ios::binary);
fout.write((char*) &student, sizeof(student));
fout.close();
vector<Student> student2;
ifstream fin("data.dat", ios::in | ios::binary);
fin.seekg(0, ifstream::end);
int size = fin.tellg() / sizeof (student2);
student2.resize(size);
fin.seekg(0, ifstream::beg);
fin.read((char*)&student2, sizeof(student2));
vector<Student>::const_iterator itr = student2.begin();
while(itr != student2.end())
{
itr->print();
++itr;
}
fin.close();
return 0;
}
但是当我运行它时。在我的linux薄荷上,我得到了这个结果:
Alex 19 Maria 20 muhamed 20 Jeniffer 20 Alex 20 Maria 21 *** glibc detected *** ./from vector to binary: corrupted double-linked list: 0x0000000000633030 ***
我是C 的新手。有些人请帮助我,过去2周陷入了这个问题。预先感谢您的答案。
您正在写作以提交向量结构,而不是其数据缓冲区。尝试将写作过程更改为:
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));
在文件中存储pods 的 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或所有向量包含相同数量的元素)。如果您的向量具有不同长度不同的POD,则必须在编写原始数据之前将矢量中的元素编写到文件中。
此外,当您以不同系统之间的数字类型传输数字类型时,请注意endianness。
用于函数read()和write(),您需要所谓的"普通旧数据"或" pod"。这基本上意味着阶级或结构必须没有指针,并且没有虚拟功能。向量的实现当然有指示 - 我不确定虚拟功能。
您必须编写一个函数,该函数一次存储学生(或者将一堆学生转换为阵列(而不是矢量)字节或某些此类函数 - 但这更复杂)。
您无法将非POD数据(特别是指示)编写到二进制文件的原因是,当您再次读回数据时,几乎可以肯定,您可以肯定的是,内存布局从编写时发生了变化。这变得有点像试图在商店的同一停车位停车 - 其他人下次出现时,其他人将在入口的第三位停放,因此您必须选择另一个位置。将编译器分配的记忆视为停车位,以及学生信息为汽车。
[从技术上讲,在这种情况下,更糟糕的是 - 您的向量实际上并不包含班级中的学生,这是您写在文件中的内容,因此您甚至没有保存有关学生的信息,只是有关其所在位置的信息(停车位数)]
您可能无法用二进制(您正在做的方式)写入任何std::vector
,因为该模板包含内部指针,编写和重新阅读它们是毫无意义的。
一些一般建议:
-
不要在二进制中写入任何STL模板容器(例如
std::vector
或std::map
),它们肯定包含您真正不想按原样编写的内部指针。如果您真的需要写它们,请实现自己的写作和阅读例程(例如使用STL迭代器)。 -
避免不小心使用
strcpy
。如果名称具有30多个字符,则您的代码将崩溃。至少,使用strncpy(m_name, name, sizeof(m_name));
(但即使在30个字符的名称中也很糟糕)。实际上,m_name
应该是std::string
。 -
明确序列化您的容器类(通过处理每个有意义的成员数据)。您可以考虑使用JSON符号(或YAML,甚至XML)来序列化。它为您提供了一种文本转储格式,您可以使用标准编辑器(例如
emacs
或gedit
)轻松检查。您会发现很多序列化的免费库,例如jsoncpp和许多其他。 -
学习使用
g++ -Wall -g
编译并使用gdb
调试器和valgrind
内存泄漏检测器;还要学习使用make
并编写您的Makefile
-S。 -
利用Linux是免费软件的优势,因此您可以查看其源代码(即使STL标头很复杂,也可能需要研究STDC 实现)。
- 如何将包含另一个对象向量的对象保存到文件中,并使用C++中的二进制文件从文件中读回?
- 将无符号字符的向量写入二进制文件 c++
- FlatBuffers:未支撑的工会向量错误将JSON文件转换为二进制文件
- 写入向量<向量<float>>到二进制文件
- 视觉读取来自二进制文件C 的2D向量
- 有没有一种优雅的方法来读取二进制文件并将其内容复制到向量<int>
- 如何从二进制文件中读取双精度并将其保存在向量中
- 将CV :: MAT的向量写入C 的二进制文件
- 使用fstream从二进制文件中读取并将结果存储在向量中
- 如何在C 中正确写入向量到二进制文件
- 将向量<double>写入二进制文件并再次读取
- 将二进制文件读取到向量元素的地址中
- 将可变大小结构的向量存储在c++中的二进制文件中
- 将包含另一个向量的结构向量写入二进制文件
- 在二进制文件c++中写入和加载结构向量
- 将二进制文件读入向量<char>读取小于完整文件
- 将二进制文件读入位集或向量<bool>
- 从二进制文件读取复数值到STL向量
- 从二进制文件中读取ublas向量或用array[]初始化它
- 将二进制文件读取到向量"unsigned char"时的模板参数是什么