【问题标题】:C++ Read and write multiple objects of same classC++ 读写同一个类的多个对象
【发布时间】:2013-08-12 12:13:12
【问题描述】:
airport air(1,2,3); //an airport constructor
ofstream myfile;
myfile.open("rishab",ios::app||ios::binary);
myfile.write((char*)air,sizeof(airport);
myfile.close();

在我的程序中多次调用此类命令以获取许多机场的信息。基本上二进制文件充满了机场。 稍后我需要将所有这些机场读入一个数组。如何读取文件以获取机场数组。

抱歉,如果这个问题太基本了。我在高中学习指针和最短路径图。

【问题讨论】:

  • 这取决于airport类的定义。
  • 类机场 { int planeCapacity; int acceptPlanesFrom; //和一些其他的公共整数:构造函数..访问器方法 };就是这样。
  • 我不知道是什么让人们认为您的输入文件包含对象的有效二进制转储。你没有这么说。大多数答案的方式使这个 IMO 有风险的假设。他们还提出了在c 中使用并在一定程度上有效但已过时的方法。如果您在c++ 并处理对象,那么迟早会非常糟糕。 airport 中的最小更改将破坏兼容性。你能告诉输入文件是如何创建的吗?如果不知道存储方法,您就无法真正设计阅读方法。它们是强耦合的。 airport 的定义也很有用。
  • ios::app||ios::binary 是逻辑或结果是 0 或 1。你想要按位或 ios::app|ios::binary

标签: c++ object readfile


【解决方案1】:

好吧,如果你确定你的文件是有效的,那么你可以简单地使用read() 直到你到达 EOF。 每个read() - 的sizeof(airport)- 都会给你一个有效的airport 对象。

请注意,如果对象包含指针或引用,则在加载对象时存储对象的二进制“值”将导致对象无效。

编辑:myfile.write((char*)&air,sizeof(airport); 会将air 对象的内容写入文件。通过这样做,您实际上是在编写对象,而不是指针。

【讨论】:

  • 您好,非常感谢您的回答。我现在明白我正在编写指向文件的指针并尝试读取对象。你能解释一下如何在文件上写对象而不是指针。
  • 您需要的是结构化的数据序列化,而不是 c++ 内存结构。
  • @DmitryLedentsov 是的,完全正确,除非你的类只包含基本类型(或它们本身是基本类型的对象)。
  • @Xaqq 因此,将数据和操作分开可能是有利的。序列化肯定不仅仅是“如何做”。在一个简单的例子中,一个文件转储就足够了,但很可能,这还不够好。例如,应设计数据,即避免同一对象的多次序列化和循环引用。
  • @DmitryLedentsov 我完全同意你的看法,但在这种情况下,OP 问题看起来是关于一种相当简单的序列化形式——看起来像是序列化的介绍练习。
【解决方案2】:

您正在尝试做的是序列化。这种序列化对象的方式不稳定,很大程度上取决于机场是什么。最好使用显式序列化。

Here 描述了序列化是什么以及为什么会这样。

MessagePack 中,典型的序列化-反序列化场景如下所示:

struct airport {
 std::string name; //you can name your airports here
 int planeCapacity;
 int acceptPlanesFrom;
 MSGPACK_DEFINE(name,planeCapacity,acceptPlanesFrom);
};

...

// define your airports
std::vector<airport> airports;
airport a={"BLA",1,2};
airport b={"BLB",3,4};
airports.push_back(a);
airports.push_back(b);

// create a platform-independent byte sequence from your data
msgpack::sbuffer sbuf;
msgpack::pack(sbuf, airports) ;
std::string data=sbuf.data();//you can write that into a file

msgpack::unpacked msg;
// get your data safely back
msgpack::unpack(&msg, sbuf.data(), sbuf.size());
msgpack::object obj = msg.get();

std::cout<<obj<<std::endl;

// now convert the bytes back to your objects
std::vector<airport> read_airports;
obj.convert(&read_airports);
std::cout<<read_airports.size()<<std::endl;

使用控制台输出:

[["BLA", 1, 2], ["BLB", 3, 4]]
2

【讨论】:

    【解决方案3】:
    ofstream myfile;
    
    std::vector<airport> vec;
    myfile.open("rishab",ios::app||ios::binary);
    while(myfile.write(reinterpret_cast<char*>(&air),sizeof(airport)) != 0)
       vec.push_back(air);
    
    myfile.close();
    

    现在使用vec进行处理

    【讨论】:

    • 应该是(char *)&amp;air
    • 这是否可行,因为我发送的是指向文件而不是对象的指针?抱歉刚刚混了。现在我必须遍历向量,对吧?
    【解决方案4】:

    你可以这样编程。

    struct AirPort
    {
        int a;
        int b;
        int c;
    };
    int main()
    {
        std::vector<AirPort> airportList;
        FILE* fp = fopen(filename,"rb");
        if( NULL != fp)
        {
            while(!feof(fp))
            {
                AirPort ap;
                if (fread(&ap,sizeof(ap),1,fp)==1)
                {
                    airportList.push_back(ap);
                }
            }
        }
        fclose(fp);
        return 0;
    }
    

    【讨论】:

    • 您好,谢谢。但是,我有点困惑,因为我没有做过很多向量和列表。但是,Airport 是一个类,根据我现在的理解,我正在编写一个指针值并尝试读取显然微不足道的对象。你能帮我解决我的问题吗?
    • 你的意思是如果不使用向量或列表如何编程?我不是很清楚。我的英语不是很好。你能说你想说的话吗?最好把你的 c++ 代码放在这里。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-11-21
    • 1970-01-01
    • 2018-01-04
    • 2011-07-26
    • 1970-01-01
    • 2013-08-12
    相关资源
    最近更新 更多