转自(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文件的定义(转)的更多相关文章

  1. Google Protocol Buffer的安装与.proto文件的定义

    什么是protocol Buffer呢? Google Protocol Buffer( 简称 Protobuf) 是 Google 公司内部的混合语言数据标准. 我理解的就是:它是一种轻便高效的结构 ...

  2. Google Protocol Buffer

    Google Protocol Buffer(protobuf)是一种高效且格式可扩展的编码结构化数据的方法.和JSON不同,protobuf支持混合二进制数据,它还有先进的和可扩展的模式支持.pro ...

  3. Google Protocol Buffer安装编译及使用

    近期玩了玩谷歌的Protocol Buffer.以下就简介下 Google Protocol Buffer( 简称 Protobuf) 是 Google 公司内部的混合语言数据标准.眼下已经正在使用的 ...

  4. Google Protocol Buffer 的使用和原理[转]

    本文转自: http://www.ibm.com/developerworks/cn/linux/l-cn-gpb/ Protocol Buffers 是一种轻便高效的结构化数据存储格式,可以用于结构 ...

  5. Google Protocol Buffer 的使用和原理

    Google Protocol Buffer 的使用和原理 Protocol Buffers 是一种轻便高效的结构化数据存储格式,可以用于结构化数据串行化,很适合做数据存储或 RPC 数据交换格式.它 ...

  6. 【Google Protocol Buffer】Google Protocol Buffer

    http://www.ibm.com/developerworks/cn/linux/l-cn-gpb/ Google Protocol Buffer 的使用和原理 Protocol Buffers ...

  7. 在 go/golang语言中使用 google Protocol Buffer

    怎么在go语言中实用google protocol Buffer呢? 现在的潮流趋势就是一键搞定,跟ubuntu安装软件一样 go get code.google.com/p/goprotobuf/{ ...

  8. 前端后台以及游戏中使用Google Protocol Buffer详解

    前端后台以及游戏中使用Google Protocol Buffer详解 0.什么是protoBuf protoBuf是一种灵活高效的独立于语言平台的结构化数据表示方法,与XML相比,protoBuf更 ...

  9. 转Google Protocol Buffer 的使用和原理

    Google Protocol Buffer 的使用和原理 Protocol Buffers 是一种轻便高效的结构化数据存储格式,可以用于结构化数据串行化,很适合做数据存储或 RPC 数据交换格式.它 ...

随机推荐

  1. PHP 执行命令时sudo权限的配置

    PHP 执行命令时sudo权限的配置 1.先写一个PHP文件 <?php system('whoami'); 先看自己的apache2的用户是谁,下面是笔者的截图,笔者使用apche2的用户是w ...

  2. SparkException: Master removed our application

    come from https://stackoverflow.com/questions/32245498/sparkexception-master-removed-our-application ...

  3. Dubbo和Spring Cloud微服务架构比较

    Dubbo 出生于阿里系,是阿里巴巴服务化治理的核心框架,并被广泛应用于中国各互联网公司:只需要通过 Spring 配置的方式即可完成服务化,对于应用无入侵,设计的目的还是服务于自身的业务为主. 微服 ...

  4. browser-sync & http server

    browser-sync & http server browser-sync https://www.browsersync.io/ usage # step 1 $ npm install ...

  5. 51Nod 1199 Money out of Thin Air (树链剖分+线段树)

    1199 Money out of Thin Air  题目来源: Ural 基准时间限制:1 秒 空间限制:131072 KB 分值: 80 难度:5级算法题  收藏  关注 一棵有N个节点的树,每 ...

  6. 【刷题】BZOJ 3522 [Poi2014]Hotel

    Description 有一个树形结构的宾馆,n个房间,n-1条无向边,每条边的长度相同,任意两个房间可以相互到达.吉丽要给他的三个妹子各开(一个)房(间).三个妹子住的房间要互不相同(否则要打起来了 ...

  7. 【刷题】LOJ 6005 「网络流 24 题」最长递增子序列

    题目描述 给定正整数序列 \(x_1 \sim x_n\) ,以下递增子序列均为非严格递增. 计算其最长递增子序列的长度 \(s\) . 计算从给定的序列中最多可取出多少个长度为 \(s\) 的递增子 ...

  8. 【Luogu4609】建筑师(第一类斯特林数,组合数学)

    [Luogu4609]建筑师(组合数学) 题面 洛谷 题解 首先发现整个数组一定被最高值切成左右两半,因此除去最高值之后在左右分开考虑. 考虑一个暴力\(dp\) ,设\(f[i][j]\)表示用了\ ...

  9. 【BZOJ1056】[HAOI2008]排名系统(Splay)

    [BZOJ1056][HAOI2008]排名系统(Splay) 题面 BZOJ 洛谷 题解 \(Splay\)随便维护一下就好了,至于名字什么的,我懒得手写哈希表了,直接哈希之后拿\(map\)压. ...

  10. Java: ByteBuffer在多线程中使用需要注意

    昨天我改写一个文件缓存方面程序时,用ByteBuffer替换以前用的byte[],在测试的时候抛出异常. 以前的相关代码: class A { byte[] data; ....... public  ...