Google Protocol Buffer的安装与.proto文件的定义(转)
转自(https://www.cnblogs.com/yinheyi/p/6080244.html)
什么是protocol Buffer呢?
Google Protocol Buffer( 简称 Protobuf) 是 Google 公司内部的混合语言数据标准.
我理解的就是:它是一种轻便高效的结构化数据存储格式,可以用于结构化数据串行化,或者说序列化。方便文件的存储与网络传输.
我们自己就不用定义它们的存储与传输协议了.
怎么使用protobuf呢?
第一步, 写一个proto的文件 .定义你需要的数据结构.
每二步, 使用你想要用的语言的proto文件编译器把写的proto文件编译为目标语言的相关类. (目前google提供了 C++、Java、Python 三种语言的 API).
第三步, 把第二步生成的类包含到你写的程序中, 就可以使用它了.
看个基于C++主语言的例子,下面是一个.proto文件,
package information // 定义了package的名字 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;
}当我们命名这个文件时,用一个良好的命名习惯: 以这个的格式,packagename.MessageName.proto,所以这里的话,我们可以把这个文件命名为 information.Person.proto
然后,我们把.proto文件用编译器编译成C++的代码以后生成了两个文件:information.Person.h和information.Person.cc文件.
现在我们就可以用它了.
如定义一个Person的类对象,然后设置它里面的值(通过类的方法),populate,
Person person;
person.set_name("John Doe");
person.set_id(1234);
person.set_email("jdoe@example.com");
fstream output("myfile", ios::out | ios::binary);
person.SerializeToOstream(&output); //把它序列化到输入输出流中,这里就是写文件中了.然后呢,我们可以从文件中再次retrieve出来 .
fstream input("myfile", ios::in | ios::binary); //读出文件
Person person;
person.ParseFromIstream(&input); //反序列化它
cout << "Name: " << person.name() << endl;
cout << "E-mail: " << person.email() << endl;
protobuf的安装:
方法一: 如果你用的ubuntu或debian的话,可以运行: sudo apt-get install protobuf-complier 命令直接安装.
方法二: 可以参考这里,https://github.com/google/protobuf,里面是什么我没有怎么仔细看哦,如果想简单安装的话,可以来这里下载protobuf-2.5.0tar.gz, 链接为:http://pan.baidu.com/s/1i5jsGiL,密码:50fo,下载完以后执行下面操作:
1,执行 tar –zxf protobuf-2.5.0.tar.gz 命令,解压文件;
2,执行 cd protobuf-2.5.0命令,进入目录。
3,执行 ./configure --prefix=加自己想安装到的绝对目录, 设置安装目录;
4,执行:make 进行编译
5, 执行: make check
6,执行: make install 进行安装;
最后呢, 加入它的环境变量,可以上系统找到它: export PATH= /home/work /protobuf/bin:$PATH
然后,你在shell里执行: protoc –version 命令,就会显示 libprotoc 2.5.0.
安装成功;
.proto文件的格式:
首先,我们定义一个.proto文件,下面的消息SearchRequest定义了3个字段.并以此为例:
message SearchRequest {
required string query = 1;
optional int32 page_number = 2;
optional int32 result_per_page = 3;
}
字段的类型: 可以为标量形式,如 string, int32等 ,也可以为复合形式,如枚举类型或其它的message类型,常见的类型如下(能看清哈):
分配的标记: 如上面所示,它们后面都有一个数字,干什么用的呢?它们的作用就是在以二进制形式的时候,可能通过这个分配的数字标记标识对应的字段,数字的范围可以从1至2次方-1. 1-15占一个字节(包括这个数字与字段类型),16-2047占两个字节.另个19000-19999是保留的数字标记. 在使用标记时,尽可能让经常出现的字段表示为1-15. 还有,我们要小的标记为将来使用.
字段的rules:
required: 在一个well-formed mmessage里,一定 要在这么一个字段.
optional: 表示可以存在可以不存在的字段.
repeated: 表示可以重复的字段,重复的次数可以为0哦. 另外,这些重复的values的顺序也会被保留下来.由于历史原因,为了让repeated的字段可以更好的encode,现在的新代码都会使一个选项[packed = true],如: repeated int32 samples = 4 [packed=true];
注意:当使用required字段的时候,要特征特别特别的小心哦,为什么呢?当我们在一个meassage里面定义了required字段的时候,如果我们有时候不想写它或着发送requied字段的时候,这时候就会出现问题,old readers会认为这个message不完整,它们就会把拒绝或着丢掉它. 所以,google的很多工程师认为,required的good 小于 harm, 所以他们选择只用optional 和repeated.
我们可以在一个.proto文件里面定义多个message.在.proto文件里面,我们用 // 来增加注释.
保留字段:在我们在删除或者注释了一个字段后,如果后来有别人使用了我们的.proto文件,为了防止别人再用我们删除或着注释过的字段的标记或名字时出现访问时的数据错误,我们应该保留我们使用过的字段的标记或名字.方法如下:
message Foo {
reserved 2, 15, 9 to 11;
reserved "foo", "bar";
} //注意:我们不能把标记与名字和放到一个 reserved里.
对于optional 字段, 我们可以设置它的默认值.当optional字段没有一个value的时候,就用默认的value代替.格式比如:
optional int32 result_per_page = 3 [default = 10];//就就是默认10了.
另外,如果我们没有设置认字段的时候,它会根据类型,设置系统的默认value. 对于 string, 默认为空字符, 对于bool类型, 默认为 false , 对于 数字类型,默认为0, 对于枚举类型,默认列表里的第一个值(所以啊,设置枚举类型时,一定特别注意啦)
message SearchRequest {
required string query = 1;
optional int32 page_number = 2;
optional int32 result_per_page = 3 [default = 10];
enum Corpus {
UNIVERSAL = 0;
WEB = 1;
IMAGES = 2;
LOCAL = 3;
NEWS = 4;
PRODUCTS = 5;
VIDEO = 6;
}
optional Corpus corpus = 4 [default = UNIVERSAL];
}
1. 我们可以在枚举变量里面定义一个变量的别名,方法是我们把不同变量名的变量值定义成一样的,并且设置 变量 allow_alias 变true.如:
enum EnumAllowingAlias {
option allow_alias = true; //一定变忘了,要不会出错的.
UNKNOWN = 0;
STARTED = 1; //下面的变量的值都为1
RUNNING = 1;
}2. 枚举类型的值应该为一个32位的整数, 由于枚举类型的值在encoding时,为变长整数的编码方式,对于 负数来说效率是很低的,所以不建议用负数作为值.
3. 我们可以把枚举类型定义在一个message里面,也可以定义在外面,这样的话,在一个.proro文件里,所有的message都可以使用它. 另外,也可以把一个枚举类型定义在其它的.proto文件里,使用的时候的syntax为:
MessageType.EnumType
.
我们可以使用一个message类型作为一个字段的type.
message SearchResponse {
repeated Result result = 1;
} message Result {
required string url = 1;
optional string title = 2;
repeated string snippets = 3;
}
Importy语句:
当我们想使用别的 .proto文件里定义的message的时候怎么办呢? 我们可以像在C/C++里导入头文件一样,使用import语句,可以把别的.proto文件导入进来. 如:
import "myproject/other_protos.proto";默认地,我们只能使用直接导入的.proto文件,(即,如果我们import的一个文件里又import了其它.proto文件,但是我们不能使用间接使用哦). 不过有一个方法, 可以让我们做到传递式的引用.即, import pulic notion.
// 第一个 .proto文件的位置;
//各种定义;// 第二个.proto文件 import public "第一个文件"
import "其它文件"// 各种定义// 第三个.proto文件 import "第二个文件" //这是,我们可以使用第一个文件里的定义,第二个文件里的定义,但是不能使用其它文件里的定义import文件时的搜索路经: 可以通过 –I/ –proto_path指定搜索路经, 或着it looks in the directory in which the compiler was invoked.
怎么更新一个 .proto文件
(对于这部分现在不先看,因为用不着,要不看了也没有用.)
Oneof 的使用:
当我们有很多可选的字段的时候,并且在很多情况下最多有一个字段被使用时,这时我们可以作用Oneof.如:
message SampleMessage {
oneof test_oneof {
string name = 4;
SubMessage sub_message = 9;
}
}这时,在Oneof 里的所有字段不会包含 required, optional ,或repeated 类型说明符. 它们共用一个memory,所示可以节约内存.我们可以使用case()或WhichOneof()方法来查看哪一个value被使用(使用哪一个方法决定我们使用的语言).
注意:当我们为Oneof里的多个字段设置值时,只有最后一个被设置的字段被保留下来了.
注意它的后向兼容性。
Map的使用:
可以增加一个map:
map<key_type, value_type> map_field = N;其中,key_type,可以为任意的整数或者string类型, value_type,可以为任意的类型. 如下为一个例子,我们把一个 Project的 Message类型与一个 string的value值相綁定了。
map<string, Project> projects = 3;
Packages:
它存在的目的是为了防止在.proto文件里的名字冲突. 就像C++里的命名空间差不多.如下所示:
首先我们定义了一个这个:
package foo.bar;
message Open { ... }然后再我们使用它的时候,我们要这么用:
message Foo {
...
required foo.bar.Open open = 1; //看到没,我们要加上它的package 的名字.
...
}
另外,还有很多可以选的选项,见:https://developers.google.com/protocol-buffers/docs/proto.
Google Protocol Buffer的安装与.proto文件的定义(转)的更多相关文章
- Google Protocol Buffer的安装与.proto文件的定义
什么是protocol Buffer呢? Google Protocol Buffer( 简称 Protobuf) 是 Google 公司内部的混合语言数据标准. 我理解的就是:它是一种轻便高效的结构 ...
- Google Protocol Buffer
Google Protocol Buffer(protobuf)是一种高效且格式可扩展的编码结构化数据的方法.和JSON不同,protobuf支持混合二进制数据,它还有先进的和可扩展的模式支持.pro ...
- Google Protocol Buffer安装编译及使用
近期玩了玩谷歌的Protocol Buffer.以下就简介下 Google Protocol Buffer( 简称 Protobuf) 是 Google 公司内部的混合语言数据标准.眼下已经正在使用的 ...
- Google Protocol Buffer 的使用和原理[转]
本文转自: http://www.ibm.com/developerworks/cn/linux/l-cn-gpb/ Protocol Buffers 是一种轻便高效的结构化数据存储格式,可以用于结构 ...
- Google Protocol Buffer 的使用和原理
Google Protocol Buffer 的使用和原理 Protocol Buffers 是一种轻便高效的结构化数据存储格式,可以用于结构化数据串行化,很适合做数据存储或 RPC 数据交换格式.它 ...
- 【Google Protocol Buffer】Google Protocol Buffer
http://www.ibm.com/developerworks/cn/linux/l-cn-gpb/ Google Protocol Buffer 的使用和原理 Protocol Buffers ...
- 在 go/golang语言中使用 google Protocol Buffer
怎么在go语言中实用google protocol Buffer呢? 现在的潮流趋势就是一键搞定,跟ubuntu安装软件一样 go get code.google.com/p/goprotobuf/{ ...
- 前端后台以及游戏中使用Google Protocol Buffer详解
前端后台以及游戏中使用Google Protocol Buffer详解 0.什么是protoBuf protoBuf是一种灵活高效的独立于语言平台的结构化数据表示方法,与XML相比,protoBuf更 ...
- 转Google Protocol Buffer 的使用和原理
Google Protocol Buffer 的使用和原理 Protocol Buffers 是一种轻便高效的结构化数据存储格式,可以用于结构化数据串行化,很适合做数据存储或 RPC 数据交换格式.它 ...
随机推荐
- 冲刺Two之站立会议4
在完成了对主界面的设计之后,我们对自己的聊天室界面进行了优化,添加了一些标签和图片按钮等组件让界面更加美观一些.然后还查询了一些关于改进视频和音频质量的资料,准备开展相关工作.
- 第二阶段Sprint8
昨天:把视频录制整合到时间提醒里,实现视频提醒 今天:重新规划主界面,把视频录制暂放到主页面里,先实现功能,视频提醒后期再做. 遇到的问题:还是有问题,虽然能运行,但是只能播放,不能录了啊...
- Git(2.14.1版本)学习及使用(一)
OuZeBo原创作品.转载请注明出处 http://www.cnblogs.com/OuZeBo/p/7477465.html 1.下载git:https://git-scm.com/ 2.安装(本人 ...
- Github作为图床的一个小坑
Github作为图床的一个小坑 前言 听了少铭同学建议把github作为图床,结果遇到了一个小坑,总是显示不出来图片. 问题描述与解决 形如下的链接是显示不出来的: https://github.co ...
- Vue 和 angular
vue适合移动端的项目,而angular更适合运用于Pc端的项目.
- [转帖] 常见的cmd命令
记录一下 后期用的到. ------------ 1. Echo :显示当前ECHO的状态:ECHO ON 或者ECHO OFF .2. ECHO ON :ECHO状态设为ON,将显示命令行(如每行前 ...
- Windows 下面简单的同步文件夹工具
1. 微软自己的工具 下载地址 https://www.microsoft.com/en-us/download/confirmation.aspx?id=15155 2. 安装过程忽略 3. 配置与 ...
- [转帖] 大神 Linus Torvalds 语录
My name is Linus Torvalds and I am your god.我的名字是Linus Torvalds,我是你们的上帝.(在1998 Linux大会上的自我介绍) If you ...
- SQL基本概念
目录 什么是SQL? DDL(Data Definition Language,数据定义语言) 创建数据库(CREATE) 创建表(CREATE) 删除表(DROP) 更新表(ALTER) DML(D ...
- Django时间时区问题(received a naive datetime while time zone support is active)
在django1.4以后,存在两个概念 naive time 与 active time. 简单点讲,naive time就是不带时区的时间,Active time就是带时区的时间. 举例来说,使用d ...