【问题标题】:Writing different structs to a file in C++? [closed]在 C++ 中将不同的结构写入文件? [关闭]
【发布时间】:2014-07-19 15:22:42
【问题描述】:

我需要一种方法来将三种不同类型的结构写入二进制文件,稍后必须对其进行搜索。 (例如,struct A 有两个字段,一个 int 和一个 char;struct B 有 int 和一个 long;我需要输出所有 int 等于键盘给出的结构的结构)。

我了解如何将相同类型的结构写入文件以及如何搜索它们,但是在这里我迷路了,我想出的最好的办法是声明一个包含所有可能需要的字段的结构并留下我没有的不需要空,但确实感觉不对,必须有更好的方法来做到这一点。

我已经阅读了有关二进制文件的信息,但找不到任何相关内容,大多数示例和教程都涉及编写一种数据类型。谁能指出我正确的方向?

编辑:我正在寻找@Jerry_coffin 所谓的数据库模式,并且可能会为此使用现有的数据库系统之一,这可能是最好的方法。谢谢大家的建议

【问题讨论】:

  • 你可以有一个 int 类型的第一个成员来指示它是什么类型的结构
  • 使用合理的序列化方案,例如协议缓冲区或 Boost。
  • @bits_international 这很有意义,但是在读/写时我必须使用 sizeof(struct 不管什么),所以在这种情况下,我必须首先对结构的大小做出假设,并实际学习后来是什么样的结构?
  • 如果您想要快速随机访问,实际上可能需要根据类型将一些“字段”留空。
  • 你可以使用联合。或者,如果您在编写之前拥有所有数据,请在编写时按类型和 id 对其进行排序。然后您可以在 3 次快速二进制搜索中找到

标签: c++ c struct io binaryfiles


【解决方案1】:

有两种基本的方式来处理你的数据(你还没有说哪个适用):

  1. 我认为的文字处理器模型:读入文件,根据需要使用/修改数据,在用户保存时将所有数据写回(并且可能是自动的,即使用户没有明确要求为了节省)。
  2. 我认为的数据库模式:您通常不打算一次将整个文件读入内存。您可以根据需要更新文件的各个部分。您构建文件以支持或多或少的随机访问。

如果您是第一个计划,事情就很简单了。将您的三个结构在内存中分开。当你把它们写出来时,你先写一种类型,然后是下一种类型,最后是第三种类型。您需要在某处有足够的元数据才能正确读取数据。

如果您计划使用第二个,它可能会更复杂。您有几种不同的可能性:

  1. 将数据分成三个单独的文件,分别搜索每个文件。我知道你说过你需要一个文件,但如果你能做到这一点,这可能是最干净的方法。
  2. 在您的源代码中,创建三种类型的并集,以及一个字段来说明其余类型是哪种类型。这基本上只是将特定结构不需要的空间留空,但使外部和内部表示之间的映射稍微简单一些。
  3. 构建更接近成熟数据库系统的东西。基本上,您需要将原始记录写入文件。然后你会想要某种索引来告诉每条记录从哪里开始。然后,您可能需要添加至少一个索引来帮助快速轻松地找到特定记录。
  4. 使用现有的数据库系统。 SQLite 是一个显而易见的选择。另一个不太为人所知的是STXXL。显然,SQLite 为数据提供了一个 SQL 接口,这使得支持诸如临时查询之类的事情变得更加容易(如果需要)。 STXXL 提供了一个类似于标准库中的容器的接口,但数据存储在磁盘上。这已经过大量测试和优化;通常需要付出相当多的努力才能匹配其性能。

至于哪个更可取:这取决于。单独的文件可能是最简单的。鉴于特定要求的变化很小,我可能会按照 2 中的建议设计一种类型,如果我需要存储大量数据,可能会使用 STXXL。如果您可能需要的查询更加流畅,我可能会考虑使用 SQLite。我会避免编写您自己的数据库系统,除非您的需求是非常 非常具体和不寻常的,因此您很可能会看到极有可能通过最小的努力来显着提高您的使用性能。坦率地说,我认为这不太可能。

【讨论】:

  • 我的意思是数据库模式,抱歉没有把我的问题说清楚。第四个变体可能对我来说是最好的,将研究 SQLite 或 STXXL。谢谢!
【解决方案2】:

我建议使用 protobuf

例如,假设您创建了以下 protobuf 消息。

message binary_info
{
    message struct_1
    {
        required int32 intValue = 1;
        required string strValue = 2;
    }

    message struct_2
    {
        required int32 intValue = 1;
        required uint64 ulongValue = 2;
    }

    message struct_3
    {
        required int32 intValue = 1;
        required uint64 ulongValue = 2;
        required string strValue = 3;
    }

    required struct_1 st1 = 1;
    required struct_2 st2 = 2;
    required struct_3 st3 = 3;
}

让 google protobuf 为您创建必要的文件。请参阅 https://developers.google.com/protocol-buffers/docs/overview

的开发人员指南

(在我的示例中,protoc 在communications/proto/* 处自动生成了message.pb.h 和message.pb.cc 文件)

然后您可以编写一个程序来保存和读取文件中的数据

/*
 * main.cpp
 *
 *  Created on: 30/05/2014
 *      Author: ankit
 */

#include "communications/proto/message.pb.h"
#include <iostream>
#include <fstream>


using namespace std;

bool write_data()
{
    binary_info_struct_1* s1 = new binary_info_struct_1();
    s1->set_intvalue(1);
    s1->set_strvalue("string for s1");

    binary_info_struct_2* s2 = new binary_info_struct_2();
    s2->set_intvalue(2);
    s2->set_ulongvalue(2000);

    binary_info_struct_3* s3 = new binary_info_struct_3();
    s3->set_intvalue(3);
    s3->set_ulongvalue(3000);
    s3->set_strvalue("string for s3");

    binary_info b;

    b.set_allocated_st1(s1);
    b.set_allocated_st2(s2);
    b.set_allocated_st3(s3);

    if(!b.IsInitialized())
        return false;

    fstream output("myfile.data", ios::out | ios::binary);
    b.SerializeToOstream(&output);

    return true;
}

void read_data()
{
    fstream input("myfile.data", ios::in | ios::binary);

    binary_info b;
    b.ParseFromIstream(&input);

    cout << "struct 1, int data: " << b.st1().intvalue() << endl;
    cout << "struct 1, string data: " << b.st1().strvalue() << endl;

    cout << "struct 2, int data: " << b.st2().intvalue() << endl;
    cout << "struct 2, ulong data: " << b.st2().ulongvalue() << endl;

    cout << "struct 3, int data: " << b.st3().intvalue() << endl;
    cout << "struct 3, ulong data: " << b.st3().ulongvalue() << endl;
    cout << "struct 3, string data: " << b.st3().strvalue() << endl;
}

int main()
{
    write_data();
    read_data();
    return 0;
}

希望这会有所帮助!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多