NO.2|proto3语法|消息类型|通讯录|文件读取|enum类型

发布时间:2026/5/25 3:30:02

NO.2|proto3语法|消息类型|通讯录|文件读取|enum类型 不再打印联系⼈的序列化结果⽽是将通讯录序列化后并写⼊⽂件中。从⽂件中将通讯录解析出来并进⾏打印。新增联系⼈属性共包括姓名、年龄、电话信息、地址、其他联系⽅式、备注字段规则消息的字段可以⽤下⾯⼏种规则来修饰singular消息中可以包含该字段零次或⼀次不超过⼀次。proto3语法中字段默认使⽤该规则。repeated消息中可以包含该字段任意多次包括零次其中重复值的顺序会被保留。可以理解为定义了⼀个数组。更新contacts.proto PeopleInfo 消息中新增 phone_numbers 字段表⽰⼀个联系⼈有多个号码可将其设置为repeated写法如下syntaxproto3;package contacts;message PeopleInfo{string name1;int32 age2;repeated string phone_numbers3;}消息类型的定义与使⽤定义在单个.proto⽂件中可以定义多个消息体且⽀持定义嵌套类型的消息任意多层。每个消息体中的字段编号可以重复。更新contacts.proto我们可以将phone_number提取出来单独成为⼀个消息syntaxproto3;package contacts;message PeopleInfo{string name1;int32 age2;message Phone{string number1;}}syntaxproto3;package contacts;message Phone{string number1;}message PeopleInfo{string name1;int32 age2;}使⽤消息类型可作为字段类型使⽤contacts.proto可导⼊其他.proto⽂件的消息并使⽤Phone消息定义在phone.proto⽂件中contacts.proto中的 PeopleInfo 使⽤ Phone 消息在proto3⽂件中可以导⼊proto2消息类型并使⽤它们反之亦然创建通讯录2.0版本通讯录2.x的需求是向⽂件中写⼊通讯录列表以上我们只是定义了⼀个联系⼈的消息并不能存放通讯录列表所以还需要在完善⼀下contacts.proto(终版通讯录2.0)进⾏⼀次编译protoc--cpp_out.contacts.proto编译后⽣成的 contacts.pb.h contacts.pb.cc 会将之前的⽣成⽂件覆盖掉contacts.pb.h更新的部分代码每个字段都有⼀个clear_⽅法可以将字段重新设置回empty状态。每个字段都有设置和获取的⽅法获取⽅法的⽅法名称与⼩写字段名称完全相同。但如果是消息类型的字段其设置⽅法为mutable_⽅法返回值为消息类型的指针这类⽅法会为我们开辟好空间可以直接对这块空间的内容进⾏修改。对于使⽤repeated修饰的字段也就是数组类型pb为我们提供了add_⽅法来新增⼀个值并且提供了_size⽅法来判断数组存放元素的个数。通讯录2.0的写⼊实现makefilewrite.cc// GOOGLE_PROTOBUF_VERIFY_VERSION 宏: 验证没有意外链接到与编译的头⽂件不兼容的库版本。如果检测到版本不匹配程序将中⽌。注意每个 .pb.cc ⽂件在启动时都会⾃动调⽤此宏。在使⽤ C Protocol Buffer 库之前执⾏此宏是⼀种很好的做法但不是绝对必要的。GOOGLE_PROTOBUF_VERIFY_VERSION;// 在程序结束时调⽤ ShutdownProtobufLibrary()为了删除 Protocol Buffer 库分配的所有全局对象。对于⼤多数程序来说这是不必要的因为该过程⽆论如何都要退出并且操作系统将负责回收其所有内存。但是如果你使⽤了内存泄漏检查程序该程序需要释放每个最后对象或者你正在编写可以由单个进程多次加载和卸载的库那么你可能希望强制使⽤ Protocol Buffers 来清理所有内容。google::protobuf::ShutdownProtobufLibrary();运⾏write查看⼆进制⽂件hexdump工具通讯录2.0的读取实现makefileread.cc运⾏readdecode可以⽤ protoc -h 命令来查看ProtoBuf为我们提供的所有命令option。其中ProtoBuf提供⼀个命令选项 --decode 表⽰从标准输⼊中读取给定类型的⼆进制消息并将其以⽂本格式写⼊标准输出。消息类型必须在.proto⽂件或导⼊的⽂件中定义enum类型定义规则语法⽀持我们定义枚举类型并使⽤。在.proto⽂件中枚举类型的书写规范为枚举类型名称使⽤驼峰命名法⾸字⺟⼤写。例如 MyEnum常量值名称全⼤写字⺟多个字⺟之间⽤ _ 连接。例如 ENUM_CONST 0;定义⼀个名为PhoneType的枚举类型enumPhoneType{MP0;// 移动电话TEL1;// 固定电话}0值常量必须存在且要作为第⼀个元素。这是为了与proto2的语义兼容第⼀个元素作为默认值且值为0。枚举类型可以在消息外定义也可以在消息体内定义嵌套。枚举的常量值在32位整数的范围内。但因负值⽆效因⽽不建议使⽤与编码规则有关。定义时注意将两个‘具有相同枚举值名称’的枚举类型放在单个.proto⽂件下测试时编译后会报错某某某常量已经被定义所以这⾥要注意同级同层的枚举类型各个枚举类型中的常量不能重名。单个.proto⽂件下最外层枚举类型和嵌套枚举类型不算同级。多个.proto⽂件下若⼀个⽂件引⼊了其他⽂件且每个⽂件都未声明package每个proto⽂件中的枚举类型都在最外层算同级。多个.proto⽂件下若⼀个⽂件引⼊了其他⽂件且每个⽂件都声明了package不算同级。// ---------------------- 情况1同级枚举类型包含相同枚举值名称---------------enumPhoneType{MP0;// 移动电话TEL1;// 固定电话}enumPhoneTypeCopy{MP0;// 移动电话// 编译后报错MP 已经定义}// ---------------------- 情况2不同级枚举类型包含相同枚举值名称-------------enumPhoneTypeCopy{MP0;// 移动电话// ⽤法正确}message Phone{string number1;// 电话号码enumPhoneType{MP0;// 移动电话TEL1;// 固定电话}}// ---------------------- 情况3多⽂件下都未声明package--------------------// phone1.protoimportphone1.protoenumPhoneType{MP0;// 移动电话TEL1;// 固定电话// 编译后报错MP 已经定义}// phone2.protoenumPhoneTypeCopy{MP0;// 移动电话}// ---------------------- 情况4多⽂件下都声明了package--------------------// phone1.protoimportphone1.protopackage phone1;enumPhoneType{MP0;// 移动电话TEL1;// 固定电话// ⽤法正确}// phone2.protopackage phone2;enumPhoneTypeCopy{MP0;// 移动电话}同级枚举类型包含相同枚举值名称多⽂件下都未声明package多⽂件下都声明了package升级通讯录⾄2.1版本更新contacts.proto(通讯录2.1)新增枚举字段并使⽤编译protoc--cpp_out.contacts.protocontacts.pb.h更新的部分代码对于在.proto⽂件中定义的枚举类型编译⽣成的代码中会含有与之对应的枚举类型、校验枚举值是否有效的⽅法_IsValid、以及获取枚举值名称的⽅法_Name。对于使⽤了枚举类型的字段包含设置和获取字段的⽅法已经清空字段的⽅法clear_。更新write.cc(通讯录2.1)更新read.cc(通讯录2.1)编译后进⾏读写验证

相关新闻