Google - protoc学习(一)

一、简介

Google Protocol Buffer( 简称 Protobuf) 是 Google 公司内部的混合语言数据标准。他们用于 RPC 系统和持续数据存储系统。提供一个具有高效的协议数据交换格式工具库(类似Json)。
但相比于Json,Protobuf有更高的转化效率,时间效率和空间效率都是JSON的3-5倍。
可用于通讯协议、数据存储等领域的语言无关、平台无关、可扩展的序列化结构数据格式。目前提供了 C++、Java、Python 、OC、Swift等语言的 API。总只一句话就是很好,支持多平台且与语言无关。

二、小试牛刀

2.1、编写proto文件

首先我们需要编写一个 proto 文件,定义我们程序中需要处理的结构化数据,在 protobuf 的术语中,结构化数据被称为 Message。proto 文件非常类似 java 或者 C 语言的数据定义。

package lpk;                        
message helloworld 
{ 
   required int32     id = 1;  // ID 
   required string    name = 2;  // str 
   optional int32     age = 3;  //optional field
   repeated string    gender = 4 //至少被重复0次
}
message otherMassage{
        ....
}

解释下上文内容,package 名字叫做 lpk,定义了一个消息 helloworld,该消息有三个成员,类型为 int32 的 id,另一个为类型为 string 的成员 name。age 是一个可选的成员,即消息中可以不包含该成员。proto3的语法解释;再修饰符上和proto2存在差异。

标量:正如上述文件格式,在消息定义中,每个字段都有唯一的一个数字标识符。这些标识符是用来在消息的二进制格式中识别各个字段的,一旦开始使用就不能够再改变。注:[1,15]之内的标识号在编码的时候会占用一个字节。[16,2047]之内的标识号则占用2个字节。所以应该为那些频繁出现的消息元素保留 [1,15]之内的标识号。切记:要为将来有可能添加的、频繁出现的标识号预留一些标识号。
<li>equired:一个格式良好的消息一定要含有1个这种字段。表示该值是必须要设置的;
<li>optional:消息格式中该字段可以有0个或1个值(不超过1个)。
<li>repeated:在一个格式良好的消息中,这种字段可以重复任意多次(包括0次)。重复的值的顺序会被保留。表示该值可以重复,相当于java中的List。

2.2、编译protoc文件

写好 proto 文件之后就可以用 Protobuf 编译器将该文件编译成目标语言了。我们暂且使用 C++。

假设您的 proto 文件存放在 $SRC_DIR (你的protoc文件路径)下面,您也想把生成的文件放在同一个目录下,则可以使用如下命令:

protoc -I=$SRC_DIR --cpp_out=$DST_DIR $SRC_DIR/你的protoc文件

--cpp_out 输出c++文件命令;如果要生成oc文件:--objc_out 即可;
命令将生成两个文件:

lpk.helloworld.pb.h , 定义了 C++ 类的头文件

lpk.helloworld.pb.cc , C++ 类的实现文件

OC对应的文件:
LpkHelloworld.pbobjc.h
LpkHelloworld.pbobjc.m

更多语言:<a href =http://code.google.com/intl/zh-CN/apis/protocolbuffers/docs/reference/overview.html>http://code.google.com/intl/zh-CN/apis/protocolbuffers/docs/reference/overview.html</a>

2.3、使用protoc文件

这里做简单的读写文件事例
2.3.1写入本地文件

#include "lpk.helloworld.pb.hpp"
…
 
 int main(void) 
 { 
   
  lpk::helloworld msg1; 
  msg1.set_id(101); 
  msg1.set_name(“李平宽”); 
  msg1.set_age(18); 
     
  // Write the new address book back to disk. 
  fstream output("./log", ios::out | ios::trunc | ios::binary); 
         
  if (!msg1.SerializeToOstream(&output)) { 
      count << "失败" << endl; 
      return -1; 
  }         
  return 0; 
 }

2.3.2 读取文件
#include "lpk.helloworld.pb.hpp" 
…
 void ListMsg(const lpk::helloworld & msg) { 
  cout << msg.id() << endl; 
  cout << msg.name() << endl; 
 } 
  
 int main(int argc, char* argv[]) { 
 
  lpk::helloworld msg1; 
  
  { 
    fstream input("./log", ios::in | ios::binary); 
    if (!msg1.ParseFromIstream(&input)) { 
      cerr << "读取失败" << endl; 
      return -1; 
    } 
  } 
  
  ListMsg(msg1); 
 }

运行结果:

101
李平宽

三、安装protoc

3.1 检查是否安装过或安装成功

打开终端输入 protoc --version ,如果提示有版本号则表示安装过;

lipingkuandepingmu:~ linkface$ protoc --version
libprotoc 3.6.1

3.2、安装:mac环境配置

下载地址: <a href = http://code.google.com/p/protobuf/downloads/list>http://code.google.com/p/protobuf/downloads/list</a>
两种安装方式,不过首先得安装homebrew;
首先检查电脑是否安装了homebrew,在终端输入 brew --version;

linkface$ brew --version
Homebrew 1.7.1
Homebrew/homebrew-core (git revision 0ff2c; last commit 2018-08-02)

说明已经安装过了;

如果没有安装:

/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"

然后使用 下面这两个命令;

  brew install automake
  brew install libtool

cd到你已经下载好的protoc的文件夹下;执行autogen.sh这个脚本;

./autogen.sh

然后依次执行下面命令:

./configure 
make check
make
make install

检查是否安装成功

protoc --version

另外一种安装方式直接安装,

brew protoc

四、进阶

4.1 嵌套message

嵌套是一个神奇的概念,一旦拥有嵌套能力,消息的表达能力就会非常强大。

message Person { 
 required string name = 1; 
 required int32 id = 2;        // Unique ID number for this person. 
 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; 
}

在 Message Person 中,定义了嵌套消息 PhoneNumber,并用来定义 Person 消息中的 phone 域。这使得人们可以定义更加复杂的数据结构。

4.2、import otherMessage

在一个 .proto 文件中,还可以用 Import 关键字引入在其他 .proto 文件中定义的消息,这可以称做 Import Message,或者 Dependency Message。

import common.header; 
 
message youMsg{ 
 required common.info_header header = 1; 
 required string youPrivateData = 2; 
}

其中 ,common.info_header定义在common.header包内。

Import Message 的用处主要在于提供了方便的代码管理机制,类似 C 语言中的头文件。您可以将一些公用的 Message 定义在一个 package 中,然后在别的 .proto 文件中引入该 package,进而使用其中的消息定义。

Google Protocol Buffer 可以很好地支持嵌套 Message 和引入 Message,从而让定义复杂的数据结构的工作变得非常轻松愉快。

五、其他

5.1、和其他类似技术的比较

看完这个简单的例子之后,希望您已经能理解 Protobuf 能做什么了,那么您可能会说,世上还有很多其他的类似技术啊,比如 XML,JSON,Thrift 等等。和他们相比,Protobuf 有什么不同呢?

简单说来 Protobuf 的主要优点就是:简单,快。

<b>参考:</b>
<li><a href = http://colobu.com/2015/01/07/Protobuf-language-guide/>http://colobu.com/2015/01/07/Protobuf-language-guide/</a>
<li><a href = https://www.cnblogs.com/jdonson/p/4763997.html>https://www.cnblogs.com/jdonson/p/4763997.html</a>

六、介绍下OC的使用;

主要区别是生成的OC文件。

1、使用cocoapod 引入框架

pod "ProtocolBuffers"
pod  "Protobuf"

这两个框架一个是协议,一个是路径配置文件;缺一不可;然后不需要任何和配置。

2、 将上面生成的文件拖入工程中

    #import "LpkHelloworld.pbobjc.h"


    helloworld *lpk = [[helloworld alloc] init];
    lpk.id_p = 100000;
    lpk.age = 18;
    lpk.name = @"我是一坨牛粪";
    NSData *LpkData = [lpk data];
    NSLog(@"%@",LpkData);
    
    /// 反序列化
    NSError *error ;
    helloworld  *lpkStr = [helloworld parseFromData:LpkData error:&error];
    NSLog(@"%@",lpkStr);
    NSLog(@"name = %@,age = %d",lpkStr.name,lpkStr.age);

打印结果

2018-08-07 10:21:04.602563+0800 007[20329:2150888] <08a08d06 1212e688 91e698af e4b880e5 9da8e789 9be7b2aa 1812>
2018-08-07 10:21:09.552132+0800 007[20329:2150888] <helloworld 0x6000000b3f80>: {
    id: 100000
    name: "我是一坨牛粪"
    age: 18
}
018-08-07 10:40:11.078623+0800 007[20616:2267973] name = 我是一坨牛粪,age = 18

<b>注意:这里特别提到id_p值必须给;否则data是null;</b>

3、总结

<li>使用cocoapod直接导入文件还是比较简单的不需要做任何配置。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,776评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,527评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,361评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,430评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,511评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,544评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,561评论 3 414
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,315评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,763评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,070评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,235评论 1 343
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,911评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,554评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,173评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,424评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,106评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,103评论 2 352

推荐阅读更多精彩内容

  • 由于工程项目中拟采用一种简便高效的数据交换格式,百度了一下发现除了采用 xml、JSON 还有 ProtoBuf(...
    黄海佳阅读 48,623评论 1 23
  • 翻译查阅外网资料过程中遇到的比较优秀的文章和资料,一是作为技术参考以便日后查阅,二是训练英文能力。此文翻译自 Pr...
    401阅读 67,554评论 1 39
  • 参考:http://www.jianshu.com/p/8c6c009bc500 http://blog.csdn...
    F麦子阅读 2,693评论 2 1
  • 去年有段时间得空,就把谷歌GAE的API权威指南看了一遍,收获颇丰,特别是在自己几乎独立开发了公司的云数据中心之后...
    骑单车的勋爵阅读 20,495评论 0 41
  • 逢年过节的时候,同事们总是在一起交流着给父母买礼物,吃的穿的用的,好不热闹。我不参与,因为我没有给父母买过礼物,哪...
    普雅也是花阅读 648评论 5 2