我想将对象矢量保存到文件中。最有效的方法是什么?我应该在程序启动时加载整个向量,在本地对它进行操作,然后在程序退出时保存它,或者每次我需要更改向量内部时访问文件吗?
此外,是否可以立即保存整个矢量或者我需要逐个保存元素?
答案 0 :(得分:1)
这个问题没有一个答案。
适当的方法取决于应用程序的需求,保存文件的原因以及对文件执行的操作。例如,打算在另一个程序中打开并且由人理解的文件可能与仅保存程序状态的文件(即只有软件程序需要理解它)的写入方式有很大不同。
效率最高取决于您的效率衡量标准。一些可能的措施包括写入速度,读取速度,文件大小,写入代码的大小等等。并非所有这些都在一起 - 例如,归档程序可能选择一种缓慢的方法来编写文件,为了实现快速读取速度。
通常,编写对象集合涉及单独编写所有对象,以及一些额外的簿记(例如,首先输出对象的数量),特别是如果稍后需要读取文件。但是,更智能的算法可能会从一组对象中获取某种摘要数据。例如,假设一个向量按顺序包含整数1到20。一种写作方式是写入所有20个值。另一个是简单地发出字符串" 1-20"。
答案 1 :(得分:1)
如果您的数据是POD(因此每个元素的大小相同),您可以使用以下想法。如果没有,以下想法可能很难轻易使用。
以下代码显示您可以“使用”ostream :: write“将二进制数据输出到文件中。矢量<>承诺在内存中对象是从前到后(或从前到后,如你所愿),因此它们排成一行并且相对紧凑以便传输。
使用“istream :: read”读回内存是类似的。但是在这里你需要分配缓冲1。
在下面的代码中,我分配了6个对象进行写入,然后找到了向量内存的开头,并用一个'write'写入了所有6个对象。
对于读取,我实例化并将6个对象加载到一个新向量中(请注意,向量提供了一种使用默认ctor分配和实例化对象的更流畅的方式)。
如何将写入工作中的对象数传递给读取?这可以从文件大小计算出来。 (见统计数据)
使用重新解释 - 演员不是(通常)可接受的,并且可能不可移植。但有时候你只需要这样做。
希望这个'邪恶'会促使一些更好的选择。
我离开了一些调试std :: cout的...希望你发现它们有用。
编辑 - 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数据的附加步骤(抱歉,我忘记了这个名字。)