将一些数据结构写入文件

时间:2013-06-24 06:49:54

标签: c++

想象一下,我有一个类Product的对象,其成员变量如:price, name, etc.。 并说我有10个这样的Product对象。 现在我想把所有10个人写到某个文件Products.dat。 后来我想说从文件中检索第6个产品。 通常在C ++中如何实现? (我只是感兴趣 在检索部分)。

3 个答案:

答案 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上的搜索功能直接跳转到相关数据,然后使用上面的getlineoperator>>或甚至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数据库,例如MongoDBProtocol 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);

更新,更多:如果您只需要序列化,但没有有效的查询,交易等等,您“仅仅”需要一个良好的序列化策略:JSONBSON,{{3} },Protocol BuffersMessagePackXMLBoost.Serialization可能会有所帮助