C++ 类序列化

Posted

技术标签:

【中文标题】C++ 类序列化【英文标题】:C++ Class Serialization 【发布时间】:2009-04-14 23:43:39 【问题描述】:

我最近了解了 C++ 类的朋友关键字和序列化中的用途,现在我需要一些帮助才能让它工作。

我将我的类序列化为文件没有问题,它工作得很好,但是我很难尝试将这个文件读入向量容器。我确定我的代码中需要一个循环来逐行读取,但是由于该类具有不同的类型,我想我不能使用 std::getline() 并且也许该方法不会使用 istream 方法我实施的? 示例输出文件为:

Person 1
2009
1

Person 2
2001
0

我的代码:

class SalesPeople 
    friend ostream &operator<<(ostream &stream, SalesPeople salesppl);
    friend istream &operator>>(istream &stream, SalesPeople &salesppl);

    private:
        string fullname;
        int employeeID;
        int startYear;
        bool status;
;

ostream &operator<<(ostream &stream, SalesPeople salesppl)

    stream << salesppl.fullname << endl;
    stream << salesppl.startYear << endl;
    stream << salesppl.status << endl;
    stream << endl;
    return stream;


istream &operator>>(istream &stream, SalesPeople &salesppl)

    stream >> salesppl.fullname;
    stream >> salesppl.startYear;
    stream >> salesppl.status;
    // not sure how to read that empty extra line here ?
    return stream;


// need some help here trying to read the file into a vector<SalesPeople>
SalesPeople employee;
vector<SalesPeople> employees;

ifstream read("employees.dat", ios::in);
if (!read) 
   cerr << "Unable to open input file.\n";
   return 1;


// i am pretty sure i need a loop here and should go line by line 
// to read all the records, however the class has different
// types and im not sure how to use the istream method here.

read >> employee;
employees.push_back(employee);

顺便说一句,我知道 Boost 库有一个很棒的序列化类,但是我现在正在尝试了解如何使用 STL 库进行序列化。 非常感谢您为我提供的任何帮助并让我走上正轨!

【问题讨论】:

【参考方案1】:

看起来您几乎已经拥有了所需的所有代码!我复制了您的代码并对其进行了一些更改并对其进行了编译,以从循环中的文件中读取 SalesPeople。我将在下面包含更改,但由于这是您的作业,您可能只想在查看代码之前阅读并考虑以下提示。

用于阅读销售人员 循环,我建议你采取 看看这个FAQ。它有一个 几乎完全是你的例子 需要。 FAQ 15.4 也会有所帮助 你,我相信。

关于如何处理的问题 阅读时多余的空行 从文件中,看看这个 link。你可以很简单 以这种方式提取空白。

按照 jfclavette 的建议,我会 建议调查 std::getline 用于阅读 销售员的全名,因为你 需要在那条线上的所有东西合二为一 字符串。

不过,我有一个问题要问您:employeeID 呢?我注意到它在您的示例代码中被忽略了。是故意的吗?

现在,如果您仍然需要帮助,可以查看我编写的代码以使其正常工作:

istream &operator>>(istream &stream, SalesPeople &salesppl)

    //stream >> salesppl.fullname;
    getline(stream, salesppl.fullname);
    stream >> salesppl.startYear;
    stream >> salesppl.status;
    // not sure how to read that empty extra line here ?
    stream >> ws;
    return stream;


while(read >> employee)

    // cout << employee; // to verify the input, uncomment this line
    employees.push_back(employee);

此外,正如 jfclavette 所建议的,添加一些输入验证可能不是一个坏主意(在读取流状态后检查流状态并验证它是否仍然良好)。尽管出于FAQ 15.5 中所述的原因,我建议使用while() 循环。

【讨论】:

非常感谢!!!!这有很大帮助!现在我更好地理解了我做错了什么。另外,我对ws一无所知,我一直想知道如何做到这一点很长一段时间!非常感谢! 没问题,很高兴我能帮上忙!【参考方案2】:

不确定您的问题是什么。你到底不明白什么?您的名字由多个标记组成的事实?没有神奇的方法可以做到这一点,您可能想通过 getline() 获得名称。或者,您可能希望在序列化时指定令牌数并读取适当的令牌计数。即,您的文件可能看起来像。

2 人 1

我在这里假设 Person 是名字,1 是姓氏。您也可以强制执行有一个名字和一个姓氏的概念,并分别阅读每一个。

您通常会循环 while (!ifstream.eof()) 并读取。当然,您应该始终验证输入。

另外,你为什么要在每条记录之间添加一个额外的 endl ?序列化的数据不需要很漂亮。 :)

【讨论】:

以上是关于C++ 类序列化的主要内容,如果未能解决你的问题,请参考以下文章

C++ 类序列化

如何将序列化方法添加到作为 Windows 数据结构的类成员,以便在 C++ 中与 boost 序列化一起使用

将 C++ 类序列化为文件,然后在 Python 中进行基于事件的反序列​​化?

在 C++ 中反序列化 cnn_face_detection_model_v1

C++ 序列化性能

c++中的序列化与反序列化怎么实现的?