[英]reading and writing a vector of structs to file
我读了一些关于Stack Overflow的文章,以及其他一些有关将向量写入文件的站点。 我已经实现了自己的工作方式,但遇到了一些麻烦。 结构中的数据成员之一是类字符串,并且当重新读入向量时,该数据将丢失。 同样,在编写第一个迭代之后,其他迭代也会导致malloc错误。 如何修改下面的代码,以实现将向量保存到文件中所需的功能,然后在程序再次启动时将其读回? 当前,读取是在一个类的构造函数中完成的,在析构函数中进行写入的,该类的唯一数据成员是向量,但具有操作该向量的方法。
这是我的读/写方法的要点。 假设vector<element> elements
...
读:
ifstream infile;
infile.open("data.dat", ios::in | ios::binary);
infile.seekg (0, ios::end);
elements.resize(infile.tellg()/sizeof(element));
infile.seekg (0, ios::beg);
infile.read( (char *) &elements[0], elements.capacity()*sizeof(element));
infile.close();
写:
ofstream outfile;
outfile.open("data.dat", ios::out | ios::binary | ios_base::trunc);
elements.resize(elements.size());
outfile.write( (char *) &elements[0], elements.size() * sizeof(element));
outfile.close();
结构元素:
struct element {
int id;
string test;
int other;
};
您的代码假定所有相关数据都直接存在于向量内部,而字符串是固定大小的对象,该对象的指针可以在堆中增加其大小可变的内容。 您基本上是在保存指针,而不是文本。 您应该编写一些字符串序列化代码,例如:
bool write_string(std::ostream& os, const std::string& s)
{
size_t n = s.size();
return os.write(n, sizeof n) && os.write(s.data(), n);
}
然后,您可以为您的结构编写序列化例程。 有几种设计选项:-许多人喜欢声明可以容纳std :: ostream的Binary_IStream / Binary_OStream类型,但可以使用不同的类型来创建单独的序列化例程集ala:
operator<<(Binary_OStream& os, const Some_Class&);
或者,您可以只在处理二进制序列化时放弃通常的流符号,而可以使用函数调用符号。 显然,让相同的代码正确输出二进制序列化和人类可读的序列化是很好的,因此基于操作员的方法很有吸引力。
如果要序列化数字,则需要确定是以二进制格式还是以ASCII进行序列化。 对于纯二进制格式,在需要可移植的情况下(甚至在同一OS上在32位和64位之间进行编译),您可能还需要付出一些努力来编码和使用类型大小的元数据(例如int32_t或int64_t?)。作为字节序(例如,考虑网络字节顺序和ntohl()系列功能)。 使用ASCII可以避免这些注意事项,但是它的长度可变,并且写入/读取的速度可能较慢。 在下面,我随意地将ASCII与'|'一起使用 数字的终止符。
bool write_element(std::ostream& os, const element& e)
{
return (os << e.id << '|') && write_string(os, e.test) && (os << e.other << '|');
}
然后为您的向量:
os << elements.size() << '|';
for (std::vector<element>::const_iterator i = elements.begin();
i != elements.end(); ++i)
write_element(os, *i);
阅读此内容:
std::vector<element> elements;
size_t n;
if (is >> n)
for (int i = 0; i < n; ++i)
{
element e;
if (!read_element(is, e))
return false; // fail
elements.push_back(e);
}
...需要...
bool read_element(std::istream& is, element& e)
{
char c;
return (is >> e.id >> c) && c == '|' &&
read_string(is, e.test) &&
(is >> e.other >> c) && c == '|';
}
...和...
bool read_string(std::istream& is, std::string& s)
{
size_t n;
char c;
if ((is >> n >> c) && c == '|')
{
s.resize(n);
return is.read(s.data(), n);
}
return false;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.