当前位置: 首页 > article >正文

什么是 C++ 的序列化?

什么是 C++ 的序列化?

序列化(Serialization)是指将对象的状态转换为可以存储或传输的格式的过程。它使得对象能够以二进制或文本的形式被保存到文件中,或者通过网络发送到远程计算机上,稍后可以重新构造出来(称为反序列化或 deserialization)。

在 C++ 中,序列化的目的是将内存中的对象转换成一种持久化的格式,以便它可以存储在文件中、发送到网络、或者存储在数据库中,并且之后能够恢复为原始对象。序列化不仅涉及数据本身,还包括对象的结构和状态。

序列化的基本流程

  1. 对象转换为存储格式(序列化)

    • 将对象的状态转换成一种标准格式,可以是二进制、JSON、XML 或者其他格式,适合传输或存储。
  2. 存储或传输

    • 序列化后的数据可以存储在文件系统、数据库,或者通过网络传输。
  3. 恢复对象(反序列化)

    • 反序列化是序列化的逆过程,即将存储格式的数据转换回对象,恢复成原始的对象结构和状态。

C++ 序列化的常见方法

C++ 标准库本身并没有直接支持序列化,因此开发者通常会依赖第三方库或手动实现序列化和反序列化的功能。以下是几种常见的序列化方法:

1. 手动实现序列化

C++ 中,最常见的序列化方式是手动实现。开发者需要编写代码来指定如何将对象的每个成员变量转换为字节流(存储格式),以及如何将字节流恢复为对象。

示例:手动实现序列化(文本格式)

#include <iostream>
#include <fstream>
#include <string>

class Person {
public:
    std::string name;
    int age;

    // 序列化:将对象写入文件
    void serialize(const std::string& filename) {
        std::ofstream ofs(filename);
        ofs << name << "\n" << age << "\n";
    }

    // 反序列化:从文件恢复对象
    void deserialize(const std::string& filename) {
        std::ifstream ifs(filename);
        if (ifs) {
            std::getline(ifs, name);
            ifs >> age;
        }
    }
};

int main() {
    Person p1;
    p1.name = "Alice";
    p1.age = 30;
    
    // 序列化对象
    p1.serialize("person.txt");

    // 反序列化对象
    Person p2;
    p2.deserialize("person.txt");

    std::cout << "Name: " << p2.name << ", Age: " << p2.age << std::endl;

    return 0;
}

在这个例子中:

  • 序列化serialize 方法将 nameage 两个字段以文本格式写入文件。
  • 反序列化deserialize 方法从文件中读取数据,并恢复为对象。

这种方式简单但不适用于复杂的对象(例如包含指针、动态分配的内存、成员函数等的对象),并且不支持跨平台或跨版本的数据交换。

2. 使用第三方库

由于手动序列化可能比较繁琐,许多 C++ 开发者选择使用第三方库来简化序列化的过程。常用的 C++ 序列化库包括:

  • Boost.Serialization
    Boost 提供了一个强大的序列化库,支持将对象序列化到文件、字符串流、二进制流等,并且支持反序列化。

  • Cereal
    Cereal 是一个现代 C++ 序列化库,设计简洁并且支持二进制、JSON 和 XML 格式的序列化。

  • Protobuf(Protocol Buffers)
    Google 的 Protobuf 是一个高效的跨平台序列化工具,可以自动生成序列化和反序列化代码,广泛应用于网络通信和数据存储。

  • JSON for Modern C++(nlohmann/json):
    这是一个用于 JSON 格式序列化和反序列化的流行库,操作简单,适合用来处理 JSON 数据格式。

Boost.Serialization 示例:

#include <boost/archive/text_oarchive.hpp>
#include <boost/archive/text_iarchive.hpp>
#include <iostream>
#include <sstream>

class Person {
public:
    std::string name;
    int age;

    Person() = default;
    Person(const std::string& name, int age) : name(name), age(age) {}

    // Boost 序列化函数
    template<class Archive>
    void serialize(Archive & ar, const unsigned int version) {
        ar & name;
        ar & age;
    }
};

int main() {
    // 序列化
    Person p1("Alice", 30);
    std::ostringstream oss;
    boost::archive::text_oarchive oa(oss);
    oa << p1;

    // 反序列化
    Person p2;
    std::istringstream iss(oss.str());
    boost::archive::text_iarchive ia(iss);
    ia >> p2;

    std::cout << "Name: " << p2.name << ", Age: " << p2.age << std::endl;

    return 0;
}

在这个例子中,Boost.Serialization 使用模板和流操作符 (&) 来序列化和反序列化 Person 类的成员变量。通过 text_oarchivetext_iarchive 分别进行序列化和反序列化。

3. Protobuf 示例:
#include <iostream>
#include <fstream>
#include "person.pb.h"  // 需要先生成

int main() {
    GOOGLE_PROTOBUF_VERIFY_VERSION;

    // 创建对象
    Person p1;
    p1.set_name("Alice");
    p1.set_age(30);

    // 序列化
    std::ofstream output("person.bin", std::ios::binary);
    if (!p1.SerializeToOstream(&output)) {
        std::cerr << "Failed to write person." << std::endl;
        return -1;
    }

    // 反序列化
    Person p2;
    std::ifstream input("person.bin", std::ios::binary);
    if (!p2.ParseFromIstream(&input)) {
        std::cerr << "Failed to read person." << std::endl;
        return -1;
    }

    std::cout << "Name: " << p2.name() << ", Age: " << p2.age() << std::endl;

    google::protobuf::ShutdownProtobufLibrary();
    return 0;
}

在这个例子中,使用 Protobuf 序列化和反序列化 Person 类。你需要通过 .proto 文件生成 C++ 代码,然后使用 SerializeToOstreamParseFromIstream 来进行序列化和反序列化。

4. C++ 序列化的常见场景

序列化通常应用于以下几种场景:

  • 数据存储:将对象的状态持久化到磁盘或数据库中,以便之后可以恢复。

  • 网络传输:在分布式系统中,不同节点之间通过网络传输对象数据,序列化用于将对象转化为网络可传输的格式。

  • 跨平台数据交换:当数据需要从一个平台传输到另一个平台时,使用序列化可以确保数据能够正确地被解析和重构。

  • RPC(远程过程调用):序列化通常用于将函数参数和返回值在客户端和服务器之间传输。

总结

C++ 的 序列化 是将对象转换为可存储或可传输格式的过程,通常通过手动实现或者使用第三方库(如 Boost、Protobuf)来完成。序列化的目的是为了将对象的状态持久化或在不同的系统之间传输。序列化的反向操作是 反序列化,即从存储格式恢复对象。序列化常见的应用场景包括数据存储、网络通信、跨平台数据交换等。


http://www.kler.cn/a/467134.html

相关文章:

  • 【JVM】总结篇-类的加载篇之 类的加载器 和ClassLoader分析
  • Java重要面试名词整理(二十一):SpringSecurity
  • MCGS学习记录
  • 计算机网络常见面试题及解答
  • LabVIEW在反馈控制时如何解决带约束的控制问题
  • Python 中的生成器与 yield
  • 【一文解析】新能源汽车VCU电控开发——能量回收模块
  • STM32-笔记23-超声波传感器HC-SR04
  • kubernets基础入门
  • 基于STM32的热带鱼缸控制系统的设计
  • 大模型数据采集和预处理:把所有数据格式,word、excel、ppt、jpg、pdf、表格等转为数据
  • 高清监控视频的管理与展示:从摄像头到平台的联接过程
  • 呼叫中心中间件实现IVR进入排队,判断排队超时播放提示音
  • Git快速入门(一)·Git软件的安装以及GitHubDesktop客户端的安装
  • 装饰器模式详解
  • clickhouse Cannot execute replicated DDL query, maximum retries exceeded报错解决
  • Android 14.0 系统限制上网系列之iptables用IOemNetd实现app上网黑名单的实现
  • 行为模式4.观察者模式------消息推送
  • LangChain+博查搜索API轻松实现实时信息搜索
  • 【每日学点鸿蒙知识】ASON工具、自定义tabbar、musl、Text异常截断等
  • 【C语言】可移植性陷阱与缺陷(五): 移位运算符
  • 初学stm32 --- 存储器类型
  • 文献阅读 250104-Overconfidence in climate overshoot
  • 文件上传漏洞利用与绕过姿势总结
  • 【大模型】ChatGPT 数据分析与处理使用详解
  • SQL 基础教程 - SQL SELECT 语句