我正在尝试将类“Product”的向量写入文件并将其读回。但是我在阅读时会加载垃圾。有人可以回顾一下可能出错的地方吗?或者建议另一种方法。
#include <fstream>
#include <vector>
#include <iostream>
class Product
{
public:
std::string name;
int code;
double price;
};
int
main ()
{
const char *const file_name = "products.bin";
{
std::vector < Product > prod
{
Product {"Honey", 1, 12.34},
Product {"CoffeeBeans", 2, 56.78},
Product {"Cl", 3, 90.12}
};
for (const Product & p:prod)
std::cout << p.name << ' ' << p.code << ' ' << p.price << '\n';
std::ofstream file (file_name, std::ios::binary);
size_t sz = prod.size ();
file.write (reinterpret_cast < const char *>(&sz), sizeof (sz));
file.write (reinterpret_cast < const char *>(&prod[0]), sz * sizeof (prod[0]));
}
{
std::vector < Product > prod;
std::ifstream file (file_name, std::ios::binary);
size_t sz;
file.read (reinterpret_cast < char *>(&sz), sizeof (sz));
prod.resize (sz);
file.read (reinterpret_cast < char *>(&prod[0]), sz * sizeof (prod[0]));
for (const Product & p:prod)
std::cout << p.name << ' ' << p.code << ' ' << p.price << '\n';
}
}
> Blockquote
答案 0 :(得分:2)
标准库成员std::ostream::write
将原始数据写入输出流。作为该写入的条件,所述数据本质上必须是trivially copyable。
您的Product
不是这种类型。它包含std::string
成员。 std::string
(通常)使用由对象内部指针管理的动态缓冲区实现。因此,它不是一个简单的可复制类型,因此Product
不是一个简单的可复制类型。
如果您以原始字节存储此数据,则需要协议,读者和作者都同意这一点。这个协议的复杂程度完全取决于您以及您的最终需求多么多样,而且由于您是双方的作者,这些决定完全取决于您。如果目标文件应该是多平台/字节序独立的,那么事情会很快变得复杂。如果目标只是同一平台,您可以在开发协议时跳过一些其他繁琐的细微差别。
就个人而言,我会选择一个简单的分隔文本行/记录条目。你认为通过以bin格式执行此操作而节省的空间可能是微不足道的,并且开发读者和作者都是微不足道的。作为奖励,高度可能会免费获得平台和endian独立性。
祝你好运。
答案 1 :(得分:2)
为了编写和读取非POD类型,你真的应该为每个这样的对象编写自己的序列化和反序列化函数,它按照定义的顺序写入所有对象的成员,并按顺序读取它们。此外,如果您希望数据可移植,则应记住字节顺序。
最好也为POD类型使用序列化函数。原因如下:
在对象或其成员或vtable中也有潜在的指针,你不需要的东西,也不应该序列化。
如果您使用原始数据,所有这些都会有问题。
答案 2 :(得分:1)
非POD类型(在C ++ 11之前)或非平凡可复制类型(C ++ 11)的值不能在二进制复制操作中存活。这包括使用memcpy()
创建副本,或者(正如您所做的)以二进制模式写入文件并回读。此类操作(memcpy()
,二进制读取和写入)仅具有POD类型的定义含义。
std::string
不是这种类型,因为(除此之外)它具有用户定义的构造函数,赋值运算符和管理资源(内存)的析构函数。包含不可复制类型实例的任何stuct / class类型也不是可复制类型。
答案 3 :(得分:0)
你不能写二进制文件,std :: string有动态内存。
您应该将成员写为成员,例如:
file<<prod[0].name<<' '<<prod[0].code<<' '<<prod[0].price<<' '; //You must separate diferent fields with spaces
以同样的方式阅读:
file>>prod[0].name>>prod[0].code>>prod[0].price