【问题标题】:Problems writing/reading an vector of Objects to a file [duplicate]将对象向量写入/读取到文件时出现问题[重复]
【发布时间】:2014-05-12 19:37:35
【问题描述】:

我遇到了这个问题,我想在其中创建一个设备列表,我使用设备向量来完成。但我无法使其正确读/写。

这是我的功能:

#include "Devicelist.h"

bool Devicelist::AddDevice(const char *deviceName, char *type)
{
    Device tempDevice(deviceName, type, ++id_);
    Devicelist_.push_back(tempDevice);
    return true;
}

bool Devicelist::deleteDevice(const char *deviceName)
{
    for (int i = 0; i < Devicelist_.size(); i++)
    {
        if (strcmp(deviceName, Devicelist_[i].getName()) == 0)
        {
            Devicelist_.erase(Devicelist_.begin() + i);
            return true;
        }
        else
        {
            cout << "No Device found with that Devicename." << endl;
            return false;
        }
    }
}

bool Devicelist::SaveToFile()
{
    //remove("Devices.dat");

    ofstream SaveFile("Devices.dat", ios::out | ios::binary);

    if (!SaveFile)
    {
        cerr << "File could not be opened." << endl;
        return false;
    }
    for (int i = 0; i < Devicelist_.size(); i++)
        SaveFile.write((const char *)(&Devicelist_[i]), sizeof(Devicelist_[i]));


    SaveFile.close();
    return true;
}

bool Devicelist::LoadFromFile()
{
    ifstream LoadFile("Devices.dat", ios::in | ios::binary);

    if (!LoadFile)
    {
        cerr << "File could not be opened." << endl;
        return false;
    }

    for (int i = 0; i < Devicelist_.size(); i++)
        LoadFile.read((char *)(&Devicelist_[i]), sizeof(Devicelist_[i]));


    LoadFile.close();
    return true;
}

Device Devicelist::findDevice(const char *deviceName)
{
    for (int i = 0; i < Devicelist_.size(); i++)
    {
        if (strcmp(deviceName, Devicelist_[i].getName()) == 0)
            return Devicelist_[i];
        else
            cout << "Couldn't find device." << endl;
    }
}

这是我的主要内容:

#include "Devicelist.h"

void main()
{
    Devicelist list; 
    list.AddDevice("Lampe3", "Lampe");
    list.AddDevice("Lampe4", "Lampe");
    list.SaveToFile();


    Devicelist list2;
    list2.LoadFromFile();

    Device lampe = list2.findDevice("Lampe");

    cout << lampe.getName() << endl;
    cout << lampe.getID() << endl;
    cout << lampe.getType() << endl;
}

谁能看到我的问题是什么?

提前致谢!

编辑1:

我的 Devicelist .h 文件是:

#ifndef DEVICELIST_H
#define DEVICELIST_H 

#include "Device.h"
#include <vector>
#include <string>
#include <iostream>
#include <fstream>

class Devicelist
{
public:
    Devicelist();
    bool SaveToFile();
    bool LoadFromFile();
    bool AddDevice(const char *deviceName, char *type);
    bool deleteDevice(const char *deviceName);
    Device findDevice(const char *devicename);
private:
    vector<Device> Devicelist_;
    int id_;
};

#endif

这是我的设备 .h 文件:

#ifndef DEVICE_H
#define DEVICE_H 

#include <iostream>
#include <string>

#define DNAME_SIZE 33

using namespace std;

class Device
{
public:
    Device(const char *devicename = "Default", char *type = "type", int id = 0);
    const char *getName();
    int getID();
    int getType();
private:
    char deviceName_[DNAME_SIZE];
    int id_;
    int type_;
};

#endif 

和设备 .cpp 文件:

#include "Device.h"

Device::Device(const char *deviceName, char *type, int id)
{
    strncpy_s(deviceName_, deviceName, DNAME_SIZE);

    if (type == "Lampe")
        type_ = 1;
    else if (type == "Roegalarm")
        type_ = 2;
    else if (type == "Tyverialarm")
        type_ = 3;
    else
    {
        type_ = 0;
        cout << "Type does not exists." << endl;
    }

    id_ = id;
}

const char *Device::getName()
{
    return deviceName_;
}

int Device::getID()
{
    return id_;
}

int Device::getType()
{
    return type_;
}

问题是当我尝试读取文件中保存的内容时,这是输出: http://imgur.com/P8WEAKq

【问题讨论】:

  • 什么是您面临的问题?
  • 您是否遇到编译器错误?
  • 请发帖DeviceList.h
  • 如果你给我们minimal complete example,我希望我们能在一两分钟内解决它。
  • 另外,Device 是什么?我的怀疑是您以与 POD 类型相同的方式保存非 POD 类型(只是进行内存复制),这是完全错误的。

标签: c++ vector fstream


【解决方案1】:

我认为问题出在LoadFromFile 函数中:

for (int i = 0; i < Devicelist_.size(); i++)
    LoadFile.read((char *)(&Devicelist_[i]), sizeof(Devicelist_[i]));

DeviceList 为空,或大小错误。 你可以写类似AddDevice的东西:

Device tempDevice();
LoadFile.read((char *)(&tempDevice), sizeof(tempDevice));
Devicelist_.push_back(tempDevice);

但需要知道文件的大小(设备数量)。

正如评论中提到的,这仅在Device 没有指向其他对象的指针时才有效。它应该是一个 POD(Plain Old Data)对象。

一个优雅的解决方案是在Device 上实现流式运算符

【讨论】:

  • sizeof(tempDevice) 应该是sizeof(Device),以避免混淆。虽然以这种方式'序列化'数据,但可能是非常糟糕的建议!
  • @πάντα ῥεῖ sizeof(tempDevice) 适用于大多数编译器,我使用它是因为它更容易。是的,有更好的解决方案,我只是添加了一个建议。
【解决方案2】:

在写出每个设备之前,您需要让Device::StoreToFile 写下设备的数量。这将使您的Device::LoadFromFile 知道要从文件中读取多少设备实例。

我强烈建议您不要将类或结构逐位写入文件。如果您的类或结构有任何高级数据结构,例如std::stringstd::vector,则不能将它们写成二进制。它们可能使用指向内存的指针,当您加载它们时,它们会不一样。

这是一个更好的解决方案:
1. 将 uint8_t 的缓冲区传递给 load 和 store 方法。
2. 方法从缓冲区加载或存储到缓冲区(追加)。
3.调用者读取或写入缓冲区到文件。
4. 该类还有一个“size on file”方法,返回文件占用的空间,可能与结构体大小不同。

同时在网上搜索“boost::serialization”。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-05-08
    • 2016-03-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多