【问题标题】:converting c++ class to a byte array将 C++ 类转换为字节数组
【发布时间】:2014-12-19 01:48:45
【问题描述】:

可以通过使用 ios::binary 将以下 Student 类转换为二进制文件

#include <fstream>
#include <iostream>
using namespace std;

class Student{
    public:
        char name[40], address[120], gender;
        double age;
        bool is_blabla;
};

int main() {

    Student one;
    strcpy(one.name, "Cancan Can");
    strcpy(one.address, "example example exampla");
    one.gender = 'M';
    one.age = 25;
    one.is_blabla = true;

    ofstream ofs("fifthgrade.ros", ios::binary);
    ofs.write((char *)&one, sizeof(one));

    Student two;
    ifstream ifs("fifthgrade.ros", ios::binary);
    ifs.read((char *)&two, sizeof(two));

    // check if the data is OK
    cout << "Student Name: " << two.name << endl;


    return 0;
}

文件如下:

http://i.imgur.com/GfkheWs.png

那么在这种情况下,我该如何做同样的事情来将类转换为字节(或者说 char*)数组?

编辑:但在这种情况下,假设我有一个具有方法的类。您给出的答案是告诉我编写自己的位运算符来序列化一个复杂的类。您能否参考一个很好的资源来教授如何完成它或一个小样本/示例?

Edit2:我必须避免使用额外的库,因为我可能会在无法导入大多数库的机器/编译器上反序列化序列化代码(例如,我将尝试反序列化 nvcc 编译代码上的代码)。

示例虚拟类如下所示:

class Student{
    public:
        char name[40], address[120], gender;
        double age;
        bool is_blabla;

        void set_values (int,int);
        int doubleage() {return age*2;}
};

【问题讨论】:

  • 正如下面的答案中所说,只需将数据复制到缓冲区中(vector,字符串,它们都可以正常工作。请注意,如果您没有复杂的数据,所有这些都可以正常工作类中的类型,即如果您的类是 POD(普通旧数据) > 在 C++11 中,你有一个 is_pod 方法来检查你的结构是否是一个 pod。
  • 由于字节序和对齐,它已经很复杂了。也就是说,请注意您对这种序列化格式的可移植性的假设(阅读:根本没有)。
  • @dau_sama,这个例子是一个假的。我实际上有具有动态状态和方法的复杂类。所以我明白你说的。能否请您参考我的资源/网站,以便我了解如何使用按位运算符序列化复杂类?
  • @cancan 如果你有复杂的类,这并不容易。你可以查看boost.org/doc/libs/1_55_0/libs/serialization/doc/index.html

标签: c++ arrays class serialization byte


【解决方案1】:

只需使用std::stringstream 而不是std::ofstream

然后,使用std::stringstream::str() 访问char*(此返回是std::string,您可以在其上使用std::string::c_str() 检索char*)。

【讨论】:

  • 那么,他将原始字节从他的学生对象复制到流中是好是坏?那么ios::binary 和他还问了什么?
  • 我不明白为什么生成的 char* 无法写入 ios:binary 文件。
【解决方案2】:

所有对象都可以作为它们的组成部分chars 访问,只需获取一个指针并进行转换。

尽管如此,即使您想将其写入二进制文件(与写入文本表示相反),也不要只写入其原始字节:

  • 对象可能包含许多非值位(如填充、未使用的缓冲区等)。这些可能包含以前记录的信息,您不应泄露这些信息。
  • 对象可能包含指针、句柄或其他对附加数据的引用。这些无法从按位复制中恢复,因为它们指示的信息是重要部分,不会存在。

顺便说一句:ios::binary 只是禁用文本文件的翻译。 (Unixoids 上的标识,windows 上的换行符...)

【讨论】:

  • 您能否详细说明“非价值位”?你什么意思?
  • “所有对象都可以作为其组成字符访问,只需获取一个指针并强制转换它。” 这不是很危险的误导吗?确实如此,但它忽略了 语义 构成“对象”的内容。即,您不能通过简单地将指针转换为“容器”来序列化 std::string
  • @LightnessRacesinOrbit:我稍后会解释为什么这并不总是足够好。
  • “非值位”还可能包括派生类中的 vTable 条目等内容。
  • @icabod:实际的 vtable 肯定对值有贡献,因为它决定了实际的类型。因此我宁愿把它放在隐藏的指针、句柄和其他有趣的地方。
【解决方案3】:

如果您需要更增强的方式,请考虑以下方式:

  1. Boost.Serialization (http://www.boost.org/doc/libs/1_56_0/libs/serialization/doc/index.html)
  2. Google 协议缓冲区 (https://developers.google.com/protocol-buffers/)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-12-15
    • 2017-06-08
    • 2014-08-08
    • 2021-11-30
    • 1970-01-01
    • 1970-01-01
    • 2018-01-19
    • 1970-01-01
    相关资源
    最近更新 更多