博客
关于我
Protobuf学习 - 入门
阅读量:795 次
发布时间:2023-03-04

本文共 3611 字,大约阅读时间需要 12 分钟。

Protobuf入门与使用指南

什么是Protobuf?

Protobuf(Protocol Buffers)是一种轻量级、高效的结构化数据存储格式。它平台无关、语言无关,并且支持扩展,广泛应用于通信协议和数据存储等领域。与传统的XML相比,Protobuf的解析速度快约20-100倍,序列化后的数据量也只有XML的1/3到1/10,极大地降低了数据传输和存储的成本。

为什么选择Protobuf?

  • 平台与语言无关:无需关注开发环境,直接使用即可。
  • 易用性强:提供友好的动态库,编写简单。
  • 高效解析:解析速度远快于XML等格式。
  • 数据紧凑:序列化后的数据量比XML少,传输效率高。

安装与编译

安装依赖

在安装前,确保系统已预装以下软件:

autoconf automake libtool curl make g++ unzip

编译步骤

./autogen.sh./configuremakemake checksudo make install

使用Protobuf

编写Proto文件

// addressbook.protosyntax = "proto2";package addressbook;message Person {    required string name = 1;    required int32 id = 2;    optional string email = 3;    enum PhoneType {        MOBILE = 0;        HOME = 1;        WORK = 2;    }    message PhoneNumber {        required string number = 1;        optional PhoneType type = 2 [default = HOME];    }    repeated PhoneNumber phone = 4;}message AddressBook {    repeated Person person_info = 1;}

生成C++代码

protoc -I=$SRC_DIR --cpp_out=$DST_DIR addressbook.proto

编写C++代码

#include "addressbook.pb.h"#include 
using namespace std;int main() { AddressBook person; Person* pi = person.add_person_info(); pi->set_name("aut"); pi->set_id(1219); cout << "before clear(), id = " << pi->id() << endl; pi->clear_id(); cout << "after clear(), id = " << pi->id() << endl; pi->set_id(1087); if (!pi->has_email()) { pi->set_email("autyinjing@126.com"); } PhoneNumber* pn = pi->add_phone(); pn->set_number("021-8888-8888"); pn = pi->add_phone(); pn->set_number("138-8888-8888"); pn->set_type(Person::MOBILE); uint32 size = person.ByteSize(); unsigned char byteArray[size]; person.SerializeToArray(byteArray, size); AddressBook help_person; help_person.ParseFromArray(byteArray, size); Person help_pi = help_person.person_info(0); cout << "*****************************" << endl; cout << "id: " << help_pi.id() << endl; cout << "name: " << help_pi.name() << endl; cout << "email: " << help_pi.email() << endl; for (int i = 0; i < help_pi.phone_size(); ++i) { auto help_pn = help_pi.mutable_phone(i); cout << "phone_type: " << help_pn->type() << endl; cout << "phone_number: " << help_pn->number() << endl; } cout << "*****************************" << endl; return 0;}

常用API

  • 基本操作

    • TypeName xxx() const;
    • bool has_xxx();
    • void set_xxx(const TypeName& value);
    • void clear_xxx();
  • 重复字段

    • TypeName* add_xxx();
    • TypeName xxx(int index) const;
    • TypeName* mutable_xxx(int index);
    • int xxx_size();
  • 序列化与反序列化

    • bool SerializeToOstream(std::ostream* output) const;
    • bool SerializeToString(std::string* output) const;
    • bool SerializeToArray(void* data, int size) const;
    • bool ParseFromIstream(std::istream* input);
    • bool ParseFromString(const std::string& data);
    • bool ParseFromArray(const void* data, int size);
  • 其他

    • bool IsInitialized();
    • size_t ByteSize() const;

编码规则

Base-128变长编码

  • 每个字节使用低7位存储数据,第8位(最高位)用于标识是否为最后一个字节。
  • 采用Little-Endian字节序。

ZigZag编码

  • 对于负数,将其补码转换为无符号数,再进行Base-128编码。
  • 编码公式:(n << 1) ^ (n >> 31)(或(n << 1) ^ (n >> 63))。

消息格式

  • 每个Message包含字段头和字段体。
  • 字段头由field_numberwire_type组成。
  • wire_type决定了字段的编码方式。

字段编码类型

Type Meaning Used For
0 Varint int32, int64, uint32, uint64, sint32, sint64, bool, enum
1 64-bit fixed64, sfixed64, double
2 Length-delimited string, bytes, embedded messages, packed repeated fields
3 Start group groups (废弃)
4 End group groups (废弃)
5 32-bit fixed32, sfixed32, float
6 Fixed32 fixed32, sfixed32, float
7 Fixed64 fixed64, sfixed64, double

适用场景

Protobuf在处理小型消息时效率非常高,但对于大块数据(超过1MB)其表现并不理想。因此,合理使用Protobuf,确保消息大小在合理范围内。

总结

本文介绍了Protobuf的基本使用方法和编码规则,涵盖了从安装到实际应用的全过程。更多高级功能,如反射机制、扩展、Oneof等,建议参考官方文档深入研究。

转载地址:http://fgxfk.baihongyu.com/

你可能感兴趣的文章
POI实现Excel导入Cannot get a text value from a numeric cell
查看>>
POI实现Excel导入时提示NoSuchMethodError: org.apache.poi.util.POILogger.log
查看>>
POI实现Excel导出时常用方法说明
查看>>
POI导出Excel2003
查看>>
POI数据获取及坐标纠偏
查看>>
Quartz入门看这一篇文章就够了
查看>>
POI解析Excel【poi的坑——空行处理】
查看>>
POI:POI+JXL实现xls文件添加水印
查看>>
POI:POI实现docx文件添加水印
查看>>
POJ 1006
查看>>
Quartz中时间表达式的设置-----corn表达式
查看>>
poj 1035
查看>>
POJ 1061 青蛙的约会 (扩展欧几里得)
查看>>
Quartz2.2.1简单使用
查看>>
POJ 1080 Human Gene Functions(DP:LCS)
查看>>
Quant 开源项目教程
查看>>
POJ 1088 滑雪
查看>>
POJ 1095 Trees Made to Order
查看>>
POJ 1113 Wall(计算几何--凸包的周长)
查看>>
poj 1125Stockbroker Grapevine(最短路)
查看>>