《protobuf》基础语法

文章目录

  • 消息体定义
  • 字段规则
  • 编译选项
  • 实战:编写一个通讯录文件

消息体定义

  • 文件内定义
message Phone
{string number = 1;
}message PeopleInfo
{string name = 1;int32 age = 2;Phone phone = 3;
}
  • 内嵌定义
message PeopleInfo
{string name = 1;int32 age = 2;message Phone{string number = 1;}Phone phone = 3;
}
  • 文件外定义
// 文件 Phone.proto
syntax = "proto3";
package phone;message Phone
{string number = 1;
}
import "Phone.proto";
message PeopleInfo
{string name = 1;int32 age = 2;// 引⼊的⽂件声明了package,使⽤消息时,需要⽤ ‘命名空间.消息类型’ 格式phone.Phone phone = 3;
}

字段规则

消息的字段可以用下面几种规则来修饰:

  • singular :消息中可以包含该字段零次或⼀次(不超过⼀次)。proto3 语法中,字段默认使⽤该
    规则
  • repeated :消息中可以包含该字段任意多次(包括零次),其中重复值的顺序会被保留。可以理解为定义了⼀个数组。

续回上篇,继续完善contacts.proto文件的内容

syntax = "proto3";
package contacts;message PeopleInfo
{string name = 1;int32 age = 2;// 采用内嵌式message Phone{string number = 1;}// repeated 修饰词 修饰的变量相当于数组repeated Phone phone = 3;
}// 通讯录
message Contacts
{repeated PeopleInfo contacts = 1;
}

编译选项

补充上篇:

  • -h : protoc -h 表示帮助
    在这里插入图片描述
    上图是所有内容,下面重点讲解一下 - decode
  • decode
    在这里插入图片描述大概意思是:从标准输入读取给定类型的二进制消息,并以文本格式将其写入标准输出。消息类型必须在PROTO FILES或其导入中定义。

先看用法

protoc -decode=contacts.Contacts contacts.proto < contacts.bin

在这里插入图片描述
执行指令后,结果如下
在这里插入图片描述
这个编译条件可以快速查看序列化后二进制文件的内容,是一个很便捷的操作

查看二进制内容的工具还有hexdump

hexdump:是Linux下的一个二进制文件查看工具,它可以将二进制文件转换为ASCII、八进制、十进制、十六进制格式进行查看。
-C: 表示每个字节显示为16进制和相应的ASCII字符

hexdump -C 二进制文件名
eg:hexdump -C contact.bin

在这里插入图片描述

实战:编写一个通讯录文件

上面完善编写了contacts.proto文件,现在完成写文件write.cpp和读文件read.cpp,write.cpp文件主要用于将通讯录信息通过protobuf的序列化,然后写入contact.bin文件内,read.cpp文件主要用于通过protobuf的反序列化,对contact.bin文件内容的读取。

write.cpp的编写

#include<iostream>
#include<fstream>
#include"contacts.pb.h"
using namespace std;void AddPeopleInfo(contact2::PeopleInfo *people)
{cout << "--------------新增联系⼈--------------" << endl;cout << "请输⼊联系⼈姓名: ";string name;getline(cin, name);people->set_name(name);cout << "请输⼊联系⼈年龄: ";int age;cin >> age;cin.ignore(256, '\n');  // 清除缓冲区的内容,大于256或遇到'\n'停止people->set_age(age);for(int i = 1; ;++i){cout <<  "请输⼊联系⼈电话" << i << "(只输⼊回⻋完成电话新增): ";string number;getline(cin, number);if(number.empty()) break;people->add_phone()->set_number(number);}cout << "-------------添加联系⼈成功-------------" << endl;
}int main()
{contacts::Contacts con;fstream in("contact.bin", ios::in | ios::binary);if(!in)cout << "contact.bin not exist, it is being created now" << endl;// ParseFromIstream方法的作用: 读取in里的内容并将其反序列化保存起来else if(!con.ParseFromIstream(&in)){cerr << "Fail to parse" << endl;in.close();return -1;}in.close();// 写入通讯录信息// 前文有提到,repeated修饰的变量相当于数组,所以// con.add_contacts()就相当新分配了一个contacts变量AddPeopleInfo(con.add_contacts());fstream out("contact.bin", ios::out | ios::trunc | ios::binary);// SerializeToOstream方法的作用: 读取out里的内容并将其序列化保存起来if(!con.SerializeToStream(&out)){cerr << "Fail to serialize" << endl;out.close();return -1;}cout << "write success" << endl;out.close();return 0;
}

执行效果如下:
在这里插入图片描述
在这里插入图片描述

read.cpp的编写

#include <iostream>
#include <fstream>
#include "contacts.pb.h"using namespace std;void PrintfContacts(contact2::Contacts &con)
{cout << "------------- 通讯录  -------------" << endl;for(int i = 0; i < con.contacts_size(); ++i){cout << "========= 联系人 " << i+1 << " =========" << endl;const contact2::PeopleInfo people = con.contacts(i);cout << "姓名:" << people.name() << endl;cout << "年龄:" << people.age() << endl;for(int j = 0; j < people.phone_size(); ++j){auto phone = people.phone(j);cout << "号码" << j+1 << ":" << phone.number() << endl;}}cout << "-------------------------------" << endl;
}int main()
{contact2::Contacts con;fstream in("contact.bin", ios::in | ios::binary);if(!in)cout << "contact.bin not exist, it is being created now" << endl;else if(!con.ParseFromIstream(&in)){in.close();return -1;}PrintfContacts(con);in.close();return 0;
}

执行效果如下:
在这里插入图片描述

补充:主要函数的使用

  • bool ParseFromIstream(std::istream* input);
    Parse 系列的函数有很多,因为前面用了文件流提取内容,所以这里使用 Parse 系列的Istream()。
    作用:读取 input 里的内容并将其反序列化保存起来

  • add_contacts()
    因为 Contacts 里的 contacts 字段被 repeat 修饰,所以相当于数组,这个函数是专门新增一个 contacts 变量的。(ps:因为有contacts所以才是 add_contacts() ,如果是 其他 那么就会对应生成 add_其他()

  • bool SerializeToOstream(std::ostream* output) const;
    作用: 读取 output 里的内容并将其序列化保存起来

  • contacts_size();
    求变量个数(可以认为数组大小),注意 size 前面的名称是变量名称

  • set_变量名();
    代码里有出现,set_age(age),set_name(name),set_number(number) 没错,这些都是设置值的函数

以上函数均包含在 文件.pb.h 里,必要是时可以跳转进去里面学习函数使用,上面仅讲解了使用到的函数

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/73277.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

motionface respeak视频一键对口型

语音驱动视频唇部动作和视频对口型是两项不同的技术&#xff0c;但是它们都涉及到将语音转化为视觉效果。 语音驱动视频唇部动作&#xff08;语音唇同步&#xff09;&#xff1a; 语音驱动视频唇部动作是一种人工智能技术&#xff0c;它可以将语音转化为实时视频唇部动作。这…

LeetCode 2651. 计算列车到站时间:取模

【LetMeFly】2651.计算列车到站时间 力扣题目链接&#xff1a;https://leetcode.cn/problems/calculate-delayed-arrival-time/ 给你一个正整数 arrivalTime 表示列车正点到站的时间&#xff08;单位&#xff1a;小时&#xff09;&#xff0c;另给你一个正整数 delayedTime 表…

QT多语言冷实现以及注意事项

目录 1 引言2 实现步骤3 问题4 工具 1 引言 冷实现需要重启软件才会刷新软件显示资源。 2 实现步骤 创建Qt多语言翻译文件.ts&#xff0c;比如命名为Project_zh.ts。 可以通过Qt Creator直接创建翻译文件&#xff0c;也可以通过VS QT Tools进行生成。如果是Qt Creator工程。…

Vue3_pinia使用

安装 cnpm install pinia 新建store目录&#xff0c;在store目录下创建loginUser.js import { defineStore } from pinia import {ref} from vue export const userLoginStore defineStore(loginUser, () > {let loginUserInfo ref({})function setUserInfo(data){this.…

网络安全攻击的常见类型

网络安全攻击的常见类型包括以下几种&#xff1a; 木马程序&#xff08;Trojan Horse&#xff09;&#xff1a;木马程序是一种假扮成正常程序的恶意软件&#xff0c;一旦被安装或执行&#xff0c;攻击者就能够远程控制被感染的系统&#xff0c;进行非法操作。 计算机病毒&…

mac pro 查看隐藏文件夹

在Mac上查看隐藏文件夹可以使用以下方法&#xff1a; 使用终端&#xff1a; 打开终端应用程序&#xff0c;位于“应用程序”文件夹的“实用工具”子文件夹中。 在终端中&#xff0c;输入以下命令&#xff0c;然后按回车键&#xff1a; defaults write com.apple.finder AppleS…

ASP.NET Core 中的 Razor Pages

Razor Pages Razor Pages 是基于页面的 ASP.NET Core Web App 架构。 相比 MVC 模式&#xff0c;Razor Pages的生产效率更快。 Razer Pages 需要两个中间件&#xff1a; builder…Services.AddRazorPages 添加 Razor Pages servicesapp.MapRazorPages 添加 Razor Pages endpo…

gis:读取shp文件

public static void readShpFile(String shpPath) {File shpFile new File(shpPath);try {// 通过给定的shapefile路径创建ShapefileDataStore对象ShapefileDataStore shapefileDataStore new ShapefileDataStore(shpFile.toURI().toURL());// 设置编码为UTF-8&#xff0c;以…

Vue中如何实现城市3D分布图

cityfenbu.vue <template><div ><el-card class"seriesmap-box-card"><div slot"header" class"clearfix"><span>城市分布图 (点击可下钻到县)</span></div><div><div class"series-ma…

【科研论文配图绘制】task8 总结与回顾

task8 总结与回顾&#xff0c;这次组队学习大致掌握了常见python绘图工具包的使用&#xff0c;整体上和matlab的语法类似&#xff0c;也是用画布形式控制元素的绘制。印象深刻的是seaborn的使用&#xff0c;在之前做波士顿房价预测时候先接触了seaborn绘制的散点图、直方图和核…

【C++从0到王者】第二十八站:二叉搜索树的应用

文章目录 前言一、Key模型二、Key/Value模型总结 前言 二叉搜索树的在现实世界的应用很广泛&#xff0c;比如Key模型&#xff0c;Key-Value模型就是常见的两种的模型 一、Key模型 K模型&#xff1a;K模型即只有key作为关键码&#xff0c;结构中只需要存储Key即可&#xff0c…

Java是如何扩展加载Jar包?

java -jar参数运行应用时classpath的设置方法 当用java -jar yourJarExe.jar来运行一个经过打包的应用程序的时候&#xff0c;你会发现如何设置-classpath参数应用程序都找不到相应的第三方类&#xff0c;报ClassNotFound错误。实际上这是由于当使用-jar参数运行的时候&#xf…

适用于Linux的Windows子系统(系统安装步骤)

目录 前言 一、WSL2安装 1.Microsoft参考文档&#xff08;推荐选择旧版 WSL 的手动安装步骤&#xff09; 2.开启子系统 二、Ubuntu安装 1.在Microsoft Store中获取ubuntu 2.运行ubuntu配置管理信息 3.ubuntu换源 三、WSL 与 Ubuntu的一些基础使用命令 四、Windows Terminal终端…

C++新特性:智能指针

一 、为什么需要智能指针 智能指针主要解决以下问题&#xff1a; 1&#xff09;内存泄漏&#xff1a;内存手动释放&#xff0c;使用智能指针可以自动释放 2&#xff09;共享所有权指针的传播和释放&#xff0c;比如多线程使用同一个对象时析构问题&#xff0c;例如同样的数据…

C#,《小白学程序》第十八课:随机数(Random)第五,方差及标准方差(标准差)的计算方法与代码

1 文本格式 /// <summary> /// 《小白学程序》第十八课&#xff1a;随机数&#xff08;Random&#xff09;第五&#xff0c;方差及标准方差&#xff08;标准差&#xff09;的计算方法与代码 /// 方差 SUM(&#xff08;Xi - X)^2 ) / n i0...n-1 X Average of X[i] ///…

《DevOps实践指南》- 读书笔记(二)

DevOps实践指南 Part 2 从何处开始5. 选择合适的价值流作为切入点5.1 绿地项目与棕地项目5.2 兼顾记录型系统和交互型系统5.3 从最乐于创新的团队开始5.4 扩大 DevOps 的范围5.5 小结 6. 理解、可视化和运用价值流6.1 确定创造客户价值所需的团队6.2 针对团队工作绘制价值流图6…

【广州华锐互动】电厂三维数字孪生大屏的功能和优势

在工业互联网的背景下&#xff0c;电厂三维数字孪生大屏系统正在逐渐成为电力行业的重要技术。通过创建电厂的虚拟模型&#xff0c;这个数字孪生系统可以实现对实际电厂的实时监控&#xff0c;预测维护需求&#xff0c;优化运营效率&#xff0c;甚至在某些情况下&#xff0c;能…

内存溢出和内存泄漏的区别

文章目录 一、什么是内存二、定义不同三、产生原因不同四、处理方式不同五、影响程度不同六、检测工具不同 一、什么是内存 内存&#xff08;Memory&#xff09;是计算机用于存储和访问数据和指令的设备。它是计算机系统中的一个重要组成部分&#xff0c;用于临时存储和处理数…

jmeter 线程组 Open Model Thread Group 阶梯式压测、高峰流量压测

简介 Open Model Thread Group 是5.4.1 版本中引入的一个实验性线程组&#xff0c;可以弹性模拟负载测试。例如设置多个线程模式&#xff0c;再根据这些线程模式调整不同的并发数、暂停时间。由于Open Model Thread Group 是一个实验性线程组&#xff0c;可能会存在一些限制和不…

2.9 PE结构:重建导入表结构

脱壳修复是指在进行加壳保护后的二进制程序脱壳操作后&#xff0c;由于加壳操作的不同&#xff0c;有些程序的导入表可能会受到影响&#xff0c;导致脱壳后程序无法正常运行。因此&#xff0c;需要进行修复操作&#xff0c;将脱壳前的导入表覆盖到脱壳后的程序中&#xff0c;以…