《protobuf》基础语法

news2024/11/30 14:44:00

文章目录

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

消息体定义

  • 文件内定义
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.coloradmin.cn/o/991575.html

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

相关文章

如何自启动MySQL服务与解决MySQL字符集问题

1、自启动mysql服务 &#xff08;1&#xff09;查看mysql是否自启动&#xff08;默认自启动&#xff09; systemctl list-unit-files|grep mysqld.service &#xff08;2&#xff09;如不是enabled可以运行如下命令设置自启动 systemctl enable mysqld.sercice2、字符集…

[DM8] DM-DM DBLINK DPI方式

前言 对于DM与DM之间的DBLINK&#xff0c;三种方式中&#xff0c;使用DPI方式配置上最为方便&#xff0c;ODBC方式需要安装ODBC包并配置ODBC数据源&#xff0c;dmmal方式需要设置MAL_INI数据库参数、配置dmmal.ini文件并需要重启数据库服务。 dpi类型的dblink&#xff0c;达梦…

eNSP与CRT配置

1、启动所有设备 2、右键设备&#xff0c;进入“设置” 3、在设置界面中&#xff0c;进入“配置选项卡”&#xff0c;记住串口号 4、打开CRT&#xff0c;进行快速连接 5、协议选择Telnet、Hostname输入“127.0.0.1”、端口输入设备的串口号 6、最终连接效果 eNSP连接CRT配置t…

2023年9月7日

1> 封装一个结构体&#xff0c;结构体中包含一个私有数组&#xff0c;用来存放学生的成绩&#xff0c;包含一个私有变量&#xff0c;用来记录学生个数&#xff0c; 提供一个公有成员函数&#xff0c;void setNum(int num)用于设置学生个数 提供一个公有成员函数&#xff1…

Nougat:一种用于科学文档OCR的Transformer 模型

随着人工智能领域的不断进步&#xff0c;其子领域&#xff0c;包括自然语言处理&#xff0c;自然语言生成&#xff0c;计算机视觉等&#xff0c;由于其广泛的用例而迅速获得了大量的普及。光学字符识别(OCR)是计算机视觉中一个成熟且被广泛研究的领域。它有许多用途&#xff0c…

测试岗位的不足和缺点-思考

软件测试岗位在实际工作中可能会面临一些不足和缺点&#xff0c;以下是一些常见的问题&#xff1a; 高压力、高强度的工作&#xff1a;软件测试工作往往需要在项目截止日期前完成测试&#xff0c;这可能会带来巨大的压力。同时&#xff0c;如果开发团队在项目中进行了大量的更改…

shell脚本详解

当你进入Linux世界的大门时&#xff0c;就会遇到一个强大而又神奇的工具——Shell。Shell是一种命令行解释器&#xff0c;为你在Linux系统中与计算机进行互动提供了无限的可能性。 学习Shell可以让你获得强大的自动化和脚本编程能力&#xff0c;让你更高效地处理文件和目录、管…

微信小程序使用 scss

一、在 vscode 中安装 easy sass 扩展 二、在微信开发者工具导入 vscode 安装的 easy sass 扩展 安装完成后会让重新加载扩展 再次打开后就可以看到扩展已经有 easy sass 了 三、修改 easy sass 配置 重新加载扩展后&#xff0c;默认情况下这个扩展是已经启动的&#xff0c…

Cadence 设计快速入门

概述 偶然的机会看到Cadence官方给的一篇入门文章,感觉相当不错,跟着一步一步做了一下,受益匪浅,在这里记录一下这个过程。 这篇文章主要包含一个风扇控制模块的原理图设计、pcb和仿真。主要涉及如下工具 OrCAD Capture CIS PSpice AD OrCAD PCB Editor原理图设计 在本章我…

C/C++输出绝对值 2019年9月电子学会青少年软件编程(C/C++)等级考试一级真题答案解析

目录 C/C输出绝对值 一、题目要求 1、编程实现 2、输入输出 二、解题思路 1、案例分析 三、程序代码 四、程序说明 五、运行结果 六、考点分析 C/C输出绝对值 2019年9月 C/C编程等级考试一级编程题 一、题目要求 1、编程实现 输入一个浮点数&#xff0c;输出这个…

10-JVM调优工具详解

上一篇&#xff1a;09-JVM垃圾收集底层算法实现 前置启动程序 事先启动一个web应用程序&#xff0c;用jps查看其进程id&#xff0c;接着用各种jdk自带命令优化应用 1.Jmap 此命令可以用来查看内存信息&#xff0c;实例个数以及占用内存大小 jmap -histo 14660 #查看历史…

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.…

如何用J-Link仿真PY32F003系列芯片

在用国产ARM芯片&#xff0c;仿真和烧录是必须的&#xff0c;但KEIL MDK也支持国产芯片在线仿真和下载。相信大家和我一样&#xff0c;苦于不会设置J-Link走了很多弯路。不管你用盗版的&#xff0c;还是正版的&#xff0c;都支持在线仿真和下载&#xff0c;只要是ARM核&#xf…

Python—下载清华大学鹏城实验室遥感数据

当想下载清华大学鹏城实验室10m土地利用数据的时候&#xff0c;发现他们的下载方式很奇怪&#xff0c;只能一页页的点名称全选 &#xff0c;然后批量下载&#xff0c;再一个个的加入浏览器下载&#xff0c;当一次下载过多就回卡顿和下载失败&#xff0c;所以就有了想用python进…

SpringMVC之增删改查(CRUD)项目模拟

目录 前言 一、项目模拟部署 1.创建一个Maven项目 2. 导入所需依赖 数据库连接池&#xff08;jdbc.properties&#xff09; 加载驱动&#xff08;spring-mybatis.xml&#xff09; 配置数据库信息 ​编辑 日志文件配置&#xff08;log4j.xml&#xff09; Spring MVC与Maba…

高忆管理:南京取消限购 苹果新机或搭载潜望式镜头

昨日&#xff0c;两市股指盘中单边下行。到收盘&#xff0c;沪指跌1.13%报3122.35点&#xff0c;深成指跌1.84%报10321.44点&#xff0c;创业板指跌2.11%报2056.98点&#xff0c;科创50指数跌3.72%&#xff1b;两市算计成交7668亿元。行业方面&#xff0c;半导体板块大幅下挫&a…

Pyqt5-进度条(适用pyside2、pyside6)

本章,精选了几个好看的可用于实际项目中的进度条样式。先来看看几个图: 这些都是纯代码编写,本章没有废话,有的全是代码。 示例1-双半边进度条 import sys from PyQt5.QtCore import Qt, QTimer from PyQt5.QtGui import QPainter, QColor, QPen, QLinearGradient, QFont f…

live555音视频同步

文章目录 live555音视频同步通过testOnDemandRTSPServer.cpp实现&#xff0c;仅需修改部分代码即可&#xff0c;具体思路&#xff1a;注意具体代码&#xff08;对testOnDemandRTSPServer.cpp进行修改&#xff09;修改之后成功在所在目录下直接分步执行以下命令 点赞收藏加关注&…

MSYS2 如何切换镜像源(附带脚本自动修改)

这篇文章将总结【如何切换MSYS2镜像】&#xff0c;其实比较简单&#xff0c;但还是记录一下吧。 下面示例中附带一个脚本&#xff0c;这样你就不用一个个手动修改了。 1. 镜像服务配置文件 MSYS2 的所有镜像服务配置&#xff0c;都在其安装路径下的etc/pacman.d目录下 可以看到…

Vite + vue3 项目使用 amfe-flexible 和 postcss-pxtorem 实现不同屏幕自适应

amfe-flexible 和 postcss-pxtorem 可以一起使用来实现移动端的适配效果。 amfe-flexible 主要用于动态设置根元素字体大小&#xff08;rem&#xff09;&#xff0c;以根据屏幕尺寸进行自适应布局。它会根据设备的屏幕宽度计算出根元素字体大小&#xff0c;并将其设置为页面的根…