用C ++写一个文件的不同结构?

时间:2014-05-29 23:51:47

标签: c++ c struct io binaryfiles

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

我理解如何将相同类型的结构体写入文件以及如何搜索它们,但在这里我只是迷失了,我想出的最好的事情是声明一个包含所有可能需要的字段的结构并留下我不喜欢的字段#39; t需要空,但它确实感觉不对,有一个更好的方法来做到这一点。

我读过有关二进制文件的内容并且找不到任何相关内容,大多数示例和教程都涉及编写一种数据类型。有人能指出我正确的方向吗?

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

2 个答案:

答案 0 :(得分:2)

有两种基本方法可以处理您的数据(您还没有说明哪种方法适用):

  1. 我认为是文字处理器模型:读取文件,根据需要使用/修改数据,在用户保存时将所有数据写回(并且可能自动,即使用户没有明确询问保存)。
  2. 我认为是数据库模式:您通常不打算一次将整个文件读入内存。您可以根据需要更新文件的部分和部分。您构建文件以支持或多或少的随机访问。
  3. 如果您正在计划第一个,那么事情就很简单了。保持三个结构在内存中分开。当你把它们写出来时,你会写下所有类型,然后写下所有类型,最后是所有第三类。您需要在某处获得足够的元数据才能正确读取数据。

    如果您计划第二次,那可能会更复杂。沿着这条线你有几种不同的可能性:

    1. 将数据划分为三个单独的文件,并分别搜索每个文件。我知道你说你需要一个文件,但如果你能做到这一点,那可能是最干净的方法。
    2. 在源代码中,创建三种类型的并集,以及一个字段,以告知其余类型。这基本上只是将特定结构体不需要的空间留空,但在外部和内部表示之间进行映射会稍微简单一些。
    3. 构建更接近完整数据库系统的东西。基本上,您需要将原始记录写入文件。然后你会想要某种索引来告诉每条记录的起始位置。然后,您可能希望添加至少一个索引,以帮助您快速轻松地查找特定记录。
    4. 使用现有的数据库系统。 SQLite是一个显而易见的选择。另一个不为人知的是STXXL。显然,SQLite为数据提供了一个SQL接口,这使得更容易支持ad-hoc查询等事情(如果需要)。 STXXL提供类似于标准库中容器的接口,但数据存储在磁盘上。经过严格的测试和优化;通常需要相当多的努力来匹配其性能。
    5. 哪个更好:取决于。单独的文件可能是最简单的。鉴于具有最小变化的特定要求,我可能会按照2中的建议设计单一类型,如果我需要存储大量数据,可能使用STXXL。如果你可能需要的查询更加流畅,我可能会考虑SQLite。我会避免编写您自己的数据库系统,除非您的需求非常特定且不寻常,因此您很有可能只需要很少的努力就可以为您的使用带来重大的性能提升。坦率地说,我认为这不太可能。

答案 1 :(得分:0)

我建议使用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;
}

希望这有帮助!