将对象向量保存到C++中的文件中
Saving vector of objects to file in C++
我想将对象向量保存到文件中。最有效的方法是什么?我应该在程序启动时加载整个矢量,在本地对其进行操作,然后在程序退出时保存它,或者每次需要更改矢量内部的内容时访问文件吗?
此外,是否可以一次保存整个向量,或者我需要逐个保存元素?
如果您的数据是POD(因此每个元素的大小相同),您可以使用以下思想。如果没有,下面的想法可能很难轻易使用。
以下代码显示您可以使用"ostream::write"将二进制数据放入文件中。矢量<>承诺对象在内存中是从前到后(或从后到前,根据您的意愿)的,因此它们排列整齐,相对紧凑,便于传输。
使用"istream::read"读回内存也是类似的。但在这里,您需要首先分配缓冲区。
在下面的代码中,我分配了6个对象进行写入,然后找到向量内存的开头,并用一个"写入"将所有6个对象写入。
在读取过程中,我实例化了6个对象并将其加载到一个新的向量中(注意,向量提供了一种使用默认ctor分配和实例化对象的切片器方法)。
如何将对象的数量从写入工作传递到读取?这可以根据文件大小来计算。(见统计)
使用重新解释的强制转换是不可接受的,并且可能不可移植。但有时你只能这么做。
希望这种"邪恶"会促使人们做出更好的选择。
我在一些调试std::cout中离开了。。。希望你觉得它们有帮助。
edit-4/8-在某种程度上清除了代码
// create a vector of 6 clear elements to save to file
std::vector<Something> vec6W(6); // default ctor clears contents
// change several elements by init'ing them
vec6W[0].init();
// [1] is clear (all 0's)
vec6W[2].init();
vec6W[3].init();
// [4] is clear (all 0's)
vec6W[5].init();
std::cout << " vec6W.size(): " << vec6W.size() << std::endl; // 6
std::cout << " sizeof(vec6W): " << sizeof(vec6W) << std::endl; // 12
std::cout << " sizeof(something): " << sizeof(Something) << std::endl; // 100
std::cout << " sizeof(vec6W[3]): " << sizeof(vec6W[3]) << std::endl; // 100
// #elements bytes per element
std::streamsize nBytes = (vec6W.size() * sizeof(Something));
std::cout << " nBytes : " << nBytes << std::endl; // 600
// simulate a file using
std::stringstream ss;
// note size
std::cout << " ss.str().size(): " << ss.str().size() << std::endl; // 0
// identify address of 1st element of vector
// cast to a 'const char*' for 'write()' method
const char* wBuff = reinterpret_cast<const char*>(&vec6W[0]);
// report address
std::cout << " static_cast<const void*>(wBuff): " << std::hex
<< static_cast<const void*>(wBuff) << std::dec << std::endl;
//write vector to ss
ss.write(wBuff, nBytes);
std::cout << "n note ss content size change " << std::endl;
std::cout << " ss.str().size() : " << ss.str().size() << std::endl;
// //////////////////////////////////////////////////////////////////
// build a vector of 6 clear elements to create buffer for read from file
std::vector<Something> vec6R(6);
// identify address of 1st element of vector
std::cout << " &vec6R[0] : " << std::hex << (&vec6R[0]) << std::dec << std::endl;
char* rBuff = reinterpret_cast<char*>(&vec6R[0]);
// read vector from ss
(void)ss.read(rBuff, nBytes); // read back same number of bytes
// //////////////////////////////////////////////////////////////////
// confirm vec6R matches what was written vec6W
int diff = memcmp(wBuff, rBuff, nBytes);
std::cout << (diff ? "FAILED" : "wBuff MATCHES rBuff: SUCCESS") << std::endl;
// now consider comparing vec6R to vec6W element by element
当类具有虚拟方法时,可能会出现其他问题。
祝你好运。
编辑-----
指针是可以处理的,但会产生额外的工作量和一些不对称性。
相关的工作可以称为"持久存储"。
此外,还有一些工具可以简化非POD数据的附加步骤(对不起,我忘记了名称。)
适当的方法取决于应用程序的需要、保存文件的原因以及对文件的处理方法。例如,打算在另一个程序中打开并被人类理解的文件可能与仅保存程序状态的文件(即,只有软件程序需要理解它)写得非常不同。
效率最高取决于你对效率的衡量。一些可能的衡量标准包括写入速度、读取速度、文件大小、进行写入的代码大小等。并非所有这些因素都结合在一起——例如,存档程序可能会选择慢速方法来写入文件,以实现快速读取速度。
通常,编写一个对象集合需要单独编写所有对象,再加上一些额外的记账(例如,首先输出对象的数量),尤其是在以后需要读取文件的情况下。然而,更聪明的算法可能会从一组对象中导出某种汇总数据。例如,假设一个向量按顺序包含整数1到20。一种写入方式是写入全部20个值。另一种是简单地发出字符串"1-20"。
- .cpp和.h文件中的模板专用化声明
- 为什么两个不同的未命名名称空间可以共存于一个cpp文件中
- 文本文件中的单词链表
- CMake-按正确顺序将项目与C运行时对象文件链接
- 使用新行和不使用新行读取文件
- 在C++程序中输入的文本文件将不起作用,除非文本被复制和粘贴
- 挂起和取消挂起一个文件DLL
- 如何确定我已使用非编码文件到达 EOF?
- 命名空间中具有.h和.cpp文件的类
- 如何使用ndk-build.cmd构建Android.so文件
- 从包含m行的文件中提取n行,必要时(惰性地)重复该文件
- 读取文件并输入到矢量中
- 在C++中查找文件
- c++库的公共头文件中应该包含什么
- 用c++从输入文件中读取另一行
- Cppcheck生成xml转储文件
- 读取文件的最后一行并输入到链接列表时出错
- 无法编译 rtmidi 测试 cmidiin.cpp 文件, 非法指令
- 如何将内容数组写入文本文件?
- C++ Windows 驱动程序MSB3030无法复制该文件,因为它找不到