Protobuf c++使用

Python3.8

Python3.8

Conda
Python

Python 是一种高级、解释型、通用的编程语言,以其简洁易读的语法而闻名,适用于广泛的应用,包括Web开发、数据分析、人工智能和自动化脚本

什么是 Protobuf?

Protobuf(Protocol Buffers)是 Google 开发的一种高效的结构化数据序列化工具,可用于数据存储、通信协议等场景。相比 JSON/XML,它的优势是:

  • 体积更小:二进制编码,数据压缩率高;
  • 解析更快:无需解析字符串,效率是 JSON 的 5-10 倍;
  • 跨语言兼容:支持 C++、Python、Java 等多种语言;
  • 可扩展性强:新增字段不影响旧版本解析。

一、环境搭建(Ubuntu 系统)

  1. 安装依赖工具
sudo apt update
sudo apt install -y build-essential autoconf libtool pkg-config
  1. 安装 Protobuf 编译器和 C++ 库
    推荐从源码编译(版本较新,兼容性更好):
# 下载源码(以 3.20.3 为例,可替换为最新版本)
wget https://github.com/protocolbuffers/protobuf/releases/download/v3.20.3/protobuf-all-3.20.3.tar.gz

# 解压并编译
tar -zxvf protobuf-all-3.20.3.tar.gz
cd protobuf-3.20.3
./configure --prefix=/usr/local  # 安装到系统目录
make -j4  # 4线程加速编译
sudo make install
sudo ldconfig  # 刷新动态链接库

# 验证安装(输出版本号即成功)
protoc --version  # 应显示:libprotoc 3.20.3

二、Protobuf 核心语法(proto3)

Protobuf 通过 .proto 文件定义数据结构,语法简洁,核心要素如下:

  1. 基础结构
protobuf
syntax = "proto3";  // 声明使用 proto3 语法(必须第一行)
package example;    // 命名空间,避免类名冲突

// 定义消息(数据结构)
message 消息名 {
  类型 字段名 = 标签号;  // 标签号:1~53,不可重复,用于二进制编码
}
  1. 常用类型对应表
    在这里插入图片描述

  2. 字段修饰符

  • repeated:字段可重复(类似 C++ 的 vector);
  • (默认)optional:字段可存在或不存在,未设置时用默认值(如 0、空字符串)。
  1. 示例:定义一个 Person 消息
    创建 person.proto 文件:
syntax = "proto3";
package example;  // 生成 C++ 代码时会转为 namespace example

// 人员信息
message Person {
  int32 id = 1;           // 标签号 1
  string name = 2;        // 标签号 2
  string email = 3;       // 标签号 3
  bool is_student = 4;    // 标签号 4
}

// 人员列表(包含多个 Person)
message PersonList {
  repeated Person persons = 1;  // repeated 表示列表
}

三、编译 .proto 文件生成 C++ 代码

使用 protoc 编译器将 .proto 转为 C++ 代码:

# 命令格式:protoc --cpp_out=输出目录 文件名.proto
protoc --cpp_out=. person.proto  # 输出到当前目录

执行后生成两个文件:

  • person.pb.h:头文件,包含类定义(example::Person、example::PersonList);
  • person.pb.cc:源文件,包含类的实现代码(无需手动修改)。

四、C++ 代码编写(序列化与反序列化)

  1. 核心操作流程
  • 序列化:将内存中的对象转为二进制数据(用于存储 / 传输);
  • 反序列化:将二进制数据解析为内存中的对象(用于读取)。
  1. 示例代码
    创建 main.cpp:
#include <iostream>
#include <fstream>
#include <string>
#include "person.pb.h"

using namespace example;

int main() {
  GOOGLE_PROTOBUF_VERIFY_VERSION;

  // 1. 序列化:写入文件(关键:写完后关闭流)
  Person person1;
  person1.set_id(1001);
  person1.set_name("Alice");
  person1.set_email("alice@example.com");
  person1.set_is_student(true);

  Person person2;
  person2.set_id(1002);
  person2.set_name("Bob");
  person2.set_email("bob@example.com");
  person2.set_is_student(false);

  PersonList person_list;
  *person_list.add_persons() = person1;
  *person_list.add_persons() = person2;

  // 序列化:打开文件并写入,写完后关闭流(避免流占用导致后续读取失败)
  std::fstream output("person_data.bin", std::ios::out | std::ios::binary);
  if (!person_list.SerializeToOstream(&output)) {
    std::cerr << "序列化失败!" << std::endl;
    return -1;
  }
  output.close();  // 关键:关闭输出流,释放文件资源
  std::cout << "序列化成功,数据已写入 person_data.bin" << std::endl;

  // 2. 反序列化:重新打开文件读取(关键:用新的输入流,从开头读取)
  PersonList new_person_list;
  // 重新打开文件,模式为“读+二进制”,确保流位置在文件开头
  std::fstream input("person_data.bin", std::ios::in | std::ios::binary);
  if (!input.is_open()) {  // 新增:检查文件是否成功打开
    std::cerr << "无法打开文件 person_data.bin!" << std::endl;
    return -1;
  }
  if (!new_person_list.ParseFromIstream(&input)) {
    std::cerr << "反序列化失败!" << std::endl;
    input.close();
    return -1;
  }
  input.close();  // 关闭输入流

  // 3. 打印数据(确保循环逻辑正确)
  std::cout << "\n反序列化后的数据:" << std::endl;
  // 用 persons_size() 获取列表长度,循环遍历
  for (int i = 0; i < new_person_list.persons_size(); ++i) {
    const Person& p = new_person_list.persons(i);
    std::cout << "ID: " << p.id() 
              << ", Name: " << p.name() 
              << ", Email: " << p.email() 
              << ", Is Student: " << (p.is_student() ? "Yes" : "No") 
              << std::endl;
  }

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

五、编译与运行

  1. 编译代码
    使用 g++ 编译,需链接 Protobuf 库:
g++ main.cpp person.pb.cc -o proto_demo `pkg-config --cflags --libs protobuf`
  • 说明:pkg-config --cflags --libs protobuf 自动引入 Protobuf 的头文件和库路径。
  1. 运行程序
./proto_demo

成功输出:
在这里插入图片描述

您可能感兴趣的与本文相关的镜像

Python3.8

Python3.8

Conda
Python

Python 是一种高级、解释型、通用的编程语言,以其简洁易读的语法而闻名,适用于广泛的应用,包括Web开发、数据分析、人工智能和自动化脚本

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

发如雪-ty

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值