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

Protobuf 的快速使用(二)

这个部分会对通讯录进⾏多次升级,使⽤ 2.x 表⽰升级的版本,最终将会升级如下内容:
  • 不再打印联系⼈的序列化结果,⽽是将通讯录序列化后并写⼊⽂件中。
  • 从⽂件中将通讯录解析出来,并进⾏打印。
  • 新增联系⼈属性,共包括:姓名、年龄、性别、电话信息、地址、其他联系⽅式、备注。

字段规则

消息的字段可以⽤下⾯⼏种规则来修饰:
  • singular :消息中可以包含该字段零次或⼀次(不超过⼀次)。 proto3 语法中,字段默认使⽤该规则。
  • repeated :消息中可以包含该字段任意多次(包括零次),其中重复值的顺序会被保留。可以理解为定义了⼀个数组。
更新 contacts.proto , PeopleInfo 消息中新增 phone_numbers 字段,表⽰⼀个联系⼈有多个号码,可将其设置为 repeated,写法如下:
syntax = "proto3";
package contacts;
message PeopleInfo
{
    string name = 1;
    int32 age = 2;
    repeated string phone_numbers = 3;
}

多文件的使用

我们另创建一个 gender.proto 文件,其中包含了 message Gender,内容如下:

syntax = "proto3";
package gender;
message Gender
{
    string gender = 1;
}

在 contacts.proto 导入 gender.proto 文件,并使用其中定义的 message Gender。

创建通讯录 2.0 版本

通讯录 2.x 的需求是向⽂件中写⼊通讯录列表,以上我们只是定义了⼀个联系⼈的消息,并不能存放通讯录列表,所以还需要在完善⼀下 contacts.proto (终版通讯录 2.0):
syntax = "proto3";
package contacts;
message PeopleInfo
{
    string name = 1;
    int32 age = 2;
    repeated string phone_numbers = 3;
}
message Contacts
{
    repeated PeopleInfo contacts = 1;
}
接着进⾏⼀次编译:
​​​​​​​protoc --cpp_out=. contacts.proto
编译后⽣成的 contacts.pb.h contacts.pb.cc 会将上一次的生成⽂件覆盖掉

通讯录 2.0 的写入实现

write.cc

#include <iostream>
#include <fstream>
#include "contacts.pb.h"
using namespace std;
using namespace contacts;
void AddPeopleInfo(contacts::PeopleInfo *people_info_ptr)
{
    cout << "-------------新增联系⼈-------------" << endl;
    cout << "请输⼊联系⼈姓名: " << endl;
    string name;
    getline(cin, name);
    people_info_ptr->set_name(name);
    cout << "请输⼊联系⼈年龄: " << endl;
    int age;
    cin >> age;
    people_info_ptr->set_age(age);
    cin.ignore(256, '\n');
    for (int i = 1;; i++)
    {
        cout << "请输⼊联系⼈电话" << i << "(只输⼊回⻋完成电话新增):";
        string phone;
        getline(cin, phone);
        if (phone.empty())
            break;
        auto phone_numbers = people_info_ptr->add_phone_numbers();
        phone_numbers->append(phone);
    }
    cout << "-----------添加联系⼈成功-----------" << endl;
}
int main()
{
    // 先读取已存在的 contacts
    Contacts contacts;
    fstream in("contact.bin", ios::in | ios::binary );
    if (!in)
    {
        cout << "打开文件失败!" << endl;
        return -1;
    }
    if (!contacts.ParseFromIstream(&in))
    {
        cout << "反序列化失败!" << endl;
        return -1;
    }
    AddPeopleInfo(contacts.add_contacts());
    // 向磁盘⽂件写⼊新的 contacts
    fstream out("contact.bin", ios::out | ios::trunc | ios::binary);
    if (!contacts.SerializeToOstream(&out))
    {
        cout << "序列化失败!" << endl;
        in.close();
        out.close();
        return -1;
    }
    in.close();
    out.close();
    return 0;
}

makefile

write:write.cc contacts.pb.cc
	g++ -o $@ $^ -std=c++17 -lprotobuf

.PHONY:clean
clean:
	rm -f write

通讯录 2.0 的读取实现

#include <iostream>
#include <fstream>
#include "contacts.pb.h"
using namespace std;
using namespace contacts;
void PrintfContacts(const contacts::Contacts &contacts)
{
    cout<<contacts.contacts_size();
    for (int i = 0; i < contacts.contacts_size(); i++)
    {
        cout << "-------------联系⼈" << i + 1 << "-------------" << endl;
        const PeopleInfo &info = contacts.contacts(i);
        cout << "联系⼈姓名: " << info.name() << endl;
        cout << "联系⼈年龄: " << info.age() << endl;
        int j = 1;
        for (auto phone : info.phone_numbers())
        {
            cout << "联系⼈电话" << j << ": " << phone << endl;
        }
    }
}
int main()
{
    Contacts contacts;
    fstream in("contact.bin", ios::in | ios::binary);
    if (!in)
    {
        cout << "打开文件失败!" << endl;
        return -1;
    }
    if (!contacts.ParseFromIstream(&in))
    {
        cout << "反序列化失败!" << endl;
        in.close();
        return -1;
    }
    PrintfContacts(contacts);
    in.close();
    return 0;
}

makefile

.PHONY:all
all:write read
	
write:write.cc contacts.pb.cc
	g++ -o $@ $^ -std=c++17 -lprotobuf
read:read.cc contacts.pb.cc
	g++ -o $@ $^ -std=c++17 -lprotobuf
.PHONY:clean
clean:
	rm -f write read

另⼀种读取方法--decode

我们可以⽤ protoc -h 命令来查看 ProtoBuf 为我们提供的所有命令 option。其中 ProtoBuf 提供⼀个命令选项 --decode ,表⽰从标准输⼊中读取给定类型的⼆进制消息,并将其以⽂本格式写⼊标准输出。 消息类型必须在 .proto ⽂件或导⼊的⽂件中定义。
protoc --decode=contacts.Contacts contacts.proto < contact.bin

​​​​​​​

http://www.dtcms.com/a/98606.html

相关文章:

  • SVTAV1函数分析-svt_av1_cost_coeffs_txb
  • (二)创建实例
  • 人工智能之数学基础:实对称矩阵
  • AI大模型最新发布[update@202503]
  • [Vue2]v-model用于表单
  • fio磁盘测试工具使用笔记
  • Appium中元素定位的注意点
  • springboot-Spring Boot DevTools工具的使用
  • VSCODE npm: 因为在此系统上禁止运行脚本。有关详细信息,请参阅 ...
  • 浏览器 ➔ 服务器or服务器 ➔ 浏览器:
  • 第二卷:海盐城血战(37-72回)正反人物群像
  • 第一篇:系统分析师首篇
  • DFS飞机降落
  • 《HelloGitHub》第 108 期
  • AUTOSAR_StbM_详解
  • 浅谈Thread类及常见方法与线程的状态(多线程编程篇2)
  • fetch`的语法规则及常见用法
  • Document对象的常用属性和方法
  • 蓝桥杯[每日一题] 真题:管道(java版)
  • tryhackme——Windows Local Persistence
  • std::reference_wrapper 和 std::function的详细介绍
  • MySQL数据库入门到大蛇尚硅谷宋红康老师笔记 高级篇 part13
  • 【QT】QT样式设计
  • openwrt24.10.0版本上安装istoreOS的屏幕监控插件
  • CentOS 安装 zip
  • 零基础入门多媒体音频(4)-GENIVIProjectAudioManager总览
  • gdb 调试mysql
  • vue3源码分析 -- watch
  • MVC 文件夹:架构之美,开发之魂
  • 从零开始跑通3DGS教程:(三)坐标系与尺度编辑(CloudCompare)