想象一下,我有一个类Product
的对象,其成员变量如:price, name, etc.
。
并说我有10个这样的Product对象。
现在我想把所有10个人写到某个文件Products.dat
。
后来我想说从文件中检索第6个产品。
通常在C ++中如何实现? (我只是感兴趣
在检索部分)。
答案 0 :(得分:2)
如何检索数据集取决于存储数据的方式。如果您具有固定大小的结构,则可以使用fseek(file, dataSize * RecordNr, SEEK_SET);
将文件定位在预期的偏移量处,然后从那里读取数据。
这将要求,例如name
之类的字符串具有固定的最大长度,并且记录始终以已知长度存储。
如果您的数据结构长度可变,那么您可能要么计算每条记录的长度,要么必须单独阅读它们。在这种情况下,更好的选择可能是使用一些现有的库(如sqlite或XML)来管理文件内容。
可变长度结构的另一种替代方法是,将第二个文件维护为索引,存储每个记录的偏移量。
如果只需要使用带有固定长度记录的fseek进行某些分配的少量记录就足够了。
<强>更新强>
为了使用固定大小的记录,您应该在没有任何指针的情况下创建数据结构。否则你将不得不单独读/写这些成员。
对于eaxmple:
class Product
{
double Price;
int Category;
char Name[50];
char ArticleId[10];
};
而不是
class Product
{
double Price;
int Category;
char *Name;
char *ArticleId;
};
你应该知道,这样一个固定的结构,使你的程序只能在你编写的平台上运行。您无法轻松地将数据文件复制到其他平台。如果您打算与其他平台兼容,则不应使用此方法,因为它会使移植更加困难。
答案 1 :(得分:2)
我建议您首先使用文件格式,例如:
39.28
product name
other data
47.12
another product name
other data
...
然后,您可以使用ifstream
对象读取文件,使用getline()
逐个获取文本行,使用operator>>
获取数值以获取数值(但要小心)忽略该行的其余部分,以便下一个getline
不读取空行)。跟踪您正在阅读的字段和记录,直到达到所需的记录。
如果您需要更快的访问权限,则需要使用固定宽度字段,这需要更多的输出格式知识...最好先了解第二步。使用固定宽度字段,您可以使用ifstream上的搜索功能直接跳转到相关数据,然后使用上面的getline
或operator>>
或甚至ifstream::read()
开始阅读。
编辑:根据评论使示例更加明确 - 并添加product_index字段。这可能需要一些调试/调整,但基本的想法是有用的......
struct Product
{
double price_;
double product_index_;
std::string product_name_;
std::string other_data_;
friend std::ostream& operator<<(std::ostream& os, const Product& p)
{
return os << p.price_ << '\n'
<< p.product_index_ << '\n'
<< p.product_name_ << '\n'
<< p.other_data << '\n';
}
friend std::istream& operator>>(std::ostream& is, Product& p)
{
is >> p.price_ >> p.product_index_;
is.ignore(std::numeric_limits<streamsize>::max(), '\n');
getline(is, p.product_name_);
getline(p.other_data);
return is;
}
};
// to read your input file...
if (ifstream input("input.dat"))
{
Product p;
while (input >> p)
do_something_with(p);
if (!input.eof())
std::cerr << "error during parsing of input file\n";
}
else
std::cerr << "error opening input file\n";
答案 2 :(得分:1)
如果您认真对待自己的任务并关心性能,可移植性和二进制兼容性,请考虑使用NoSQL数据库,例如MongoDB或Protocol Buffers以及任何其他NoSQL数据库。
打开与数据库的连接,该连接在一个单独的进程中运行:
mongo::DBClientConnection c;
c.connect("localhost");
查询数据库看起来像这样:
std::unique_ptr<DBClientCursor> cursor =
c.query("mystore.products", BSONObj());
while (cursor->more()) {
BSONObj p = cursor->next();
std::cout << p.getStringField("name") << std::endl;
沿着"Getting Started with the C++ Driver"
的路线将对象插入数据库:
BSONObj p = BSON( "name" << "A nice book" << "price" << 42 );
c.insert("mystore.products", p);
更新,更多:如果您只需要序列化,但没有有效的查询,交易等等,您“仅仅”需要一个良好的序列化策略:JSON,BSON,{{3} },Protocol Buffers或MessagePack,XML或Boost.Serialization可能会有所帮助