什么是protocol Buffer呢?

Google Protocol Buffer( 简称 Protobuf) 是 Google 公司内部的混合语言数据标准.

我理解的就是:它是一种轻便高效的结构化数据存储格式,可以用于结构化数据串行化,或者说序列化。方便文件的存储与网络传输.

我们自己就不用定义它们的存储与传输协议了.

怎么使用protobuf呢?

第一步, 写一个proto的文件 .定义你需要的数据结构.

每二步, 使用你想要用的语言的proto文件编译器把写的proto文件编译为目标语言的相关类. (目前google提供了 C++、Java、Python 三种语言的 API).

第三步, 把第二步生成的类包含到你写的程序中, 就可以使用它了.

看个基于C++主语言的例子,下面是一个.proto文件,

package information           // 定义了package的名字

message Person {
  required ;
  required int32 id = ;
  optional ;

  enum PhoneType {
    MOBILE = ;
    HOME = ;
    WORK = ;
  }

  message PhoneNumber {
    required ;
    optional PhoneType type =  [default = HOME];
  }

  repeated PhoneNumber phone = ;
}

当我们命名这个文件时,用一个良好的命名习惯: 以这个的格式,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();
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 ;
  optional int32 page_number = ;
  optional int32 result_per_page = ;
}

字段的类型: 可以为标量形式,如 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 , ,  to ;
  reserved "foo", "bar";
}

//注意:我们不能把标记与名字和放到一个 reserved里.

对于optional 字段, 我们可以设置它的默认值.当optional字段没有一个value的时候,就用默认的value代替.格式比如:

optional int32 result_per_page =  [];  //就就是默认10了.

另外,如果我们没有设置认字段的时候,它会根据类型,设置系统的默认value. 对于 string, 默认为空字符, 对于bool类型, 默认为 false , 对于 数字类型,默认为0, 对于枚举类型,默认列表里的第一个值(所以啊,设置枚举类型时,一定特别注意啦)

我们可以增加枚举类型哦:,如下所示,我们定义了一个枚举类型。
message SearchRequest {
  required ;
  optional int32 page_number = ;
  optional int32 result_per_page =  [];
  enum Corpus {
    UNIVERSAL = ;
    WEB = ;
    IMAGES = ;
    LOCAL = ;
    NEWS = ;
    PRODUCTS = ;
    VIDEO = ;
  }
  optional Corpus corpus =  [default = UNIVERSAL];
}

1. 我们可以在枚举变量里面定义一个变量的别名,方法是我们把不同变量名的变量值定义成一样的,并且设置 变量 allow_alias 变true.如:

enum EnumAllowingAlias {
  option allow_alias = true;          //一定变忘了,要不会出错的.
  UNKNOWN = ;
  STARTED = ;              //下面的变量的值都为1
  RUNNING = ;
}

2. 枚举类型的值应该为一个32位的整数,  由于枚举类型的值在encoding时,为变长整数的编码方式,对于 负数来说效率是很低的,所以不建议用负数作为值.

3. 我们可以把枚举类型定义在一个message里面,也可以定义在外面,这样的话,在一个.proro文件里,所有的message都可以使用它.  另外,也可以把一个枚举类型定义在其它的.proto文件里,使用的时候的syntax为:MessageType.EnumType.

我们可以使用一个message类型作为一个字段的type.

message SearchResponse {
  repeated Result result = ;
}

message Result {
  required ;
  optional ;
  repeated ;
}

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 {
     ;
     SubMessage sub_message = ;
  }
}

这时,在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<;

Packages:

它存在的目的是为了防止在.proto文件里的名字冲突. 就像C++里的命名空间差不多.如下所示:

首先我们定义了一个这个:

package foo.bar;
message Open { ... }

然后再我们使用它的时候,我们要这么用:

message Foo {
  ...
  required foo.bar.Open open = ;        //看到没,我们要加上它的package 的名字.
  ...
}

另外,还有很多可以选的选项,见:https://developers.google.com/protocol-buffers/docs/proto.

参考资料:

https://developers.google.com/protocol-buffers/

http://blog.csdn.net/huguoping830623/article/details/45482725

http://www.ibm.com/developerworks/cn/linux/l-cn-gpb/

最后,如果你觉得以上内容对你提供了实质的帮助, 如果你有钱的话,如果你愿意的话,可以打赏一下我这个穷学生哦,资助我买几本书.

钱也不用太多哦, 您可以选择:2毛,5毛、1元。(靠知识创造价值, 靠知识改变生活             ——爱你们的杰克船长,么么哒)

Google Protocol Buffer的安装与.proto文件的定义的更多相关文章

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

    转自(https://www.cnblogs.com/yinheyi/p/6080244.html) 什么是protocol Buffer呢? Google Protocol Buffer( 简称 P ...

  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. rabbitmq之amqp queue

    rabbitmq作为一个消息中间件,暂存信息的能力是必不可少的. 镜像队列

  2. JavaScript 代码 优化笔记

    1. 判断某个元素是否在数组中. setCheckNodes : function (zNodes, checkIds){ var that = this; that.setAllNodesUnche ...

  3. LeetCode Encode and Decode Strings

    原题链接在这里:https://leetcode.com/problems/encode-and-decode-strings/ 题目: Design an algorithm to encode a ...

  4. Python开发程序:选课系统

    本节作业: 选课系统 角色:学校.学员.课程.讲师要求:1. 创建北京.上海 2 所学校2. 创建linux , python , go 3个课程 , linux\py 在北京开, go 在上海开3. ...

  5. 能套用的tab栏切换

    效果: 在style.js文件里封装了一个Show函数,有4个参数,di(当前点击的按钮),num(按钮个数,也可以说是下面具体内容个数),divn(一个id前缀,这个例子里是ta,),active( ...

  6. 使用CMD命令设置IP

    使用CMD命令设置IP,将下面文本保存为bat文件后执行 netsh interface ip set address name="本地连接" source=static addr ...

  7. Java基础之扩展GUI——使用字体对话框(Sketcher 5 displaying a font dialog)

    控制台程序. 为了可以选择系统支持的字体,我们定义了一个FontDialog类: // Class to define a dialog to choose a font import java.aw ...

  8. vue.js慢速入门(2)

    4.组件使用基础 什么是组件?组件可以理解为可重用的自定义HTML. 可以使用一堆组件来构造大型应用,任意类型的应用界面都可以抽象为一个组件树: 可以把组件代码按照template.style.scr ...

  9. 我们应该如何去了解JavaScript引擎的工作原理

    “读了你的几篇关于JS(变量对象.作用域.上下文.执行代码)的文章,我个人觉得有点抽象,难以深刻理解.我想请教下通过什么途径能够深入点的了解javascript解析引擎在执行代码前后是怎么工作的,ec ...

  10. transform scale 背景图片模糊怎么办?

    transform: translateZ(0) scale(1, 1); 就是这样(摊手表情),不晓得什么原理.