Protocol Buffer

protocol Buffer与JSON、XML

相同点:都是结构化数据处理工具。

差异点:

1、JSON和XML序列化是字符流,protocolBuffer序列化后不是可读的字符串,而是二进制流;

2、JSON和XML格式的数据信息都包含在了序列化之后的数据中,不需要任何其他信息就能还原序列化之后的数据。但使用Protocol Buffer时需要先定义数据的格式,还原一个序列化之后的数据需要使用到这个定义好的数据格式。

3、因为上述两个差别,Protocol Buffer序列化出来的数据要比XML格式的数据小3到10倍,解析时间快20到100倍。

 

Protocol Buffer安装

1、下载源代码:http://code.google.com/p/protobuf/downloads/list

2、解压编译安装,安装步骤如下所示:

tar -xzfprotobuf-2.1.0.tar.gz

 cd protobuf-2.1.0

 ./configure --prefix=$INSTALL_DIR

 make

 make check

 make install

 

 

Protocol Buffer的使用方式

1、编写protocol Buffer数据格式

以.proto文件存储。每个文件可以包含多个message。一个message代表一类结构化的数据。message里面定义了每一个属性的类型和名称。Protocol Buffer里属性的类型可以是像布尔型、字符串型、整数型、实数型、字符型这样的基本类型,也可以是另一个message。每一个属性需要编号,需要保证属性的序号不重叠且为正整数,通常从1开始递增,用来确定数据序列化顺序。每个属性还带有标志,共有三类标志:repeated\optional\required,分别表示属性是可重复的、可选的、必须的。可重复类型属性的取值可以是一个列表。另外,可以通过default设定属性的默认值。

示例:

message user{

         required int32 id = 1;

         optional string name = 2;

         repeated string email = 3;

         optional bool isChild = 4[default =false];

}

除此外,如果需要引用其他.proto文件中的message,可以使用import导入。

示例:

import"proto/outer_interface/facewash.proto";

注意:在最新的Protocol Buffer3中已经不再支持required类型。

 

2、编译.proto文件

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

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

 protoc -I=$SRC_DIR--cpp_out=$DST_DIR $SRC_DIR/example.proto

命令将生成两个文件:

example.pb.h 定义了 C++ 类的头文件

example.pb.cc  C++ 类的实现文件

3、编写 writer 和 Reader

清单 2. Writer 的主要代码

 #include "lm.helloworld.pb.h"

int main(void)

 {

 

 lm::helloworld msg1;

 msg1.set_id(101);

 msg1.set_str(“hello”);

   

  //Write the new address book back to disk.

  fstreamoutput("./log", ios::out | ios::trunc | ios::binary);

       

  if(!msg1.SerializeToOstream(&output)) {

     cerr << "Failed to write msg." << endl;

     return -1;

 }        

 return 0;

 }

Msg1 是一个 helloworld 类的对象,set_id() 用来设置 id 的值。SerializeToOstream 将对象序列化后写入一个 fstream 流。

代码清单 3 列出了 reader 的主要代码。

清单 3. Reader

 #include "lm.helloworld.pb.h"

 voidListMsg(const lm::helloworld & msg) {

 cout << msg.id() << endl;

 cout << msg.str() << endl;

 }

 

 intmain(int argc, char* argv[]) {

 

 lm::helloworld msg1;

 

  {

   fstream input("./log", ios::in | ios::binary);

    if(!msg1.ParseFromIstream(&input)) {

     cerr << "Failed to parse address book." << endl;

     return -1;

    }

  }

 

 ListMsg(msg1);

  …

 }

同样,Reader 声明类 helloworld 的对象 msg1,然后利用 ParseFromIstream 从一个 fstream 流中读取信息并反序列化。此后,ListMsg 中采用 get 方法读取消息的内部信息,并进行打印输出操作。

 

 文章内容并非完全原创。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值