protocol buffer2

本文是转载别人文章,文章出处是http://blog.csdn.net/majianfei1023/article/details/45112415

 

google protobuf学习笔记二:使用和原理

标签: google protobuf数据存储protocol buffers二进制结构
  5922人阅读  评论(0)  收藏  举报
  分类:

目录(?)[+]

欢迎转载,转载请注明原文地址:http://blog.csdn.net/majianfei1023/article/details/45112415


Windows下google protobuf开发环境配置:http://blog.csdn.net/majianfei1023/article/details/45371743

一.什么是protobuf

protobuf全称Google Protocol Buffers,是google开发的的一套用于数据存储,网络通信时用于协议编解码的工具库。它和XML或者JSON差不多,也就是把某种数据结构的信息,以某种格式(XML,JSON)保存起来,protobuf与XML和JSON不同在于,protobuf是基于二进制的。主要用于数据存储、传输协议格式等场合。那既然有了XML等工具,为什么还要开发protobuf呢?主要是因为性能,包括时间开销和空间开销:

1.时间开销:XML格式化(序列化)和XML解析(反序列化)的时间开销是很大的,在很多时间性能上要求很高的场合,你能做的就是看着XML干瞪眼了。

2.空间开销:熟悉XML语法的同学应该知道,XML格式为了有较好的可读性,引入了一些冗余的文本信息。所以空间开销也不是太好(应该说是很差,通常需要实际内容好几倍的空间)。

据实验(当然不是我实验),一条消息数据,用protobuf序列化后的大小是json格式的十分之一,xml格式的二十分之一。

这一篇主要讲protobuf用作数据存储方面,下一篇讲用作rpc通讯协议方面。

二.使用protobuf

注:我只会讲语言特性,至于环境配置之类的,请大家http://blog.csdn.net/majianfei1023/article/details/45371743

protobuf的使用很简单,开发人员按照一定的语法定义结构化的消息格式,然后用自带的变异工具,工具将自动生成相关的类,官方支持Java、c++、Python语言环境(当然可以在网上找到很多支持其他语言的封装,当然你也可以自己写一个,只要符合google定义的格式)。通过将这些类包含在项目中,可以很轻松的调用相关方法来完成业务消息的序列化与反序列化工作。

1.定义报文格式。protobuf文件的后缀是proto,是一种类似c++或者java的语法。使用protoc.exe(windows平台下,你可以下载源码编译,也可以网上直接下载exe,这个大家自行Google)把proto文件编译成c++,java或者Python就可以使用了。

[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. package tutorial;  
  2.   
  3. message Person {  
  4.   required string name = 1;  
  5.   required int32 age = 2;  
  6.   optional string email = 3;  
  7.   
  8. }  


在这里定义了一个Person,我们只是简单的定义了name,age和email。这里注意,在上例中,package 名字叫做 tutorial,相当于c++的namespace,定义了一个消息 Person,该消息有3个成员,类型为 string 的 name,类型为 int32 的成员 age和类型为string的email。optional 代表这是一个可选的成员,即消息中可以不包含该成员,required代表是必须的。

写好proto之后把proto放在protoc.exe相同目录,然后在此目录使用指令:protoc --cpp_out=d:\proto person.proto(我们使用的是c++)。当用protocolbuffer编译器来运行.proto文件时,编译器将生成所选择语言的代码,这些代码可以操作在.proto文件中定义的消息类型,包括获取、设置字段值,将消息序列化到一个输出流中,以及从一个输入流中解析消息。

就可以生成person.pb.h,person.pb.cc.在生成的头文件中,定义了一个 C++ 类 Person,继承自google::protobuf::Message,后面我们进行对Person数据的文件读写, 将使用这个类来对消息进行操作。诸如对消息的成员进行赋值,将消息序列化等等都有相应的方法。

首先,把数据写入disk:

[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. #include <iostream>  
  2. #include<fstream>  
  3. #include "person.pb.h"  
  4.   
  5. #pragma comment(lib, "libprotobuf.lib")  
  6. #pragma comment(lib, "libprotoc.lib")  
  7.   
  8. using namespace std;  
  9. using namespace tutorial;  
  10.   
  11. int main()  
  12. {  
  13.     Person person;  
  14.   
  15.     person.set_name("flamingo");     
  16.     person.set_age(18);   
  17.     person.set_email("majianfei1023@gmail.com");  
  18.   
  19.     // Write  
  20.     fstream output("./log", ios::out | ios::trunc | ios::binary);  
  21.   
  22.     if (!person.SerializeToOstream(&output)) {  
  23.         cerr << "Failed to write msg." << endl;  
  24.         return -1;  
  25.     }  
  26.   
  27.     system("pause");  
  28.     return 0;  
  29. }  

namespace tutorial就是我们之前定义的package,我们先定义一个Person,然后给Person赋值,其中set_name,set_age,set_email是根据proto自动生成的,我们使用SerializeToOstream 将对象序列化成二进制(导致了可读性差的问题,这算是protobuf的一个缺点吧)后写入一个 fstream 流。

然后在从disk读出Person的数据:

[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. #include <iostream>  
  2. #include<fstream>  
  3. #include "person.pb.h"  
  4.   
  5. #pragma comment(lib, "libprotobuf.lib")  
  6. #pragma comment(lib, "libprotoc.lib")  
  7.   
  8. using namespace std;  
  9. using namespace tutorial;  
  10.   
  11. void PrintInfo(const Person & person) {   
  12.     cout << person.name() << endl;   
  13.     cout << person.age() << endl;   
  14.     cout << person.email() << endl;  
  15. }   
  16.   
  17. int main()  
  18. {  
  19.     Person person;    
  20.   
  21.     fstream input("./log", ios::in | ios::binary);  
  22.       
  23.     if (!person.ParseFromIstream(&input)) {  
  24.         cerr << "Failed to parse address book." << endl;  
  25.         return -1;  
  26.     }  
  27.   
  28.     PrintInfo(person);  
  29.   
  30.     system("pause");  
  31.     return 0;  
  32. }  


主要是利用 ParseFromIstream 从一个 fstream 流中读取序列化的信息并反序列化。



下一篇将讲利用protobuf rpc进行数据传输。



2
0
 
 
我的同类文章

参考知识库

img
Python知识库

img
Java EE知识库

img
Java SE知识库

img
Java Web知识库

img
Swift知识库

猜你在找
iOS开发高级专题—数据存储
iOS8开发视频教程Swift语言版-Part 10:iOS的数据持久化
iOS8开发视频教程-Part 4:iOS数据源协议、委托协议与高级视图
iOS网络编程-AFNetworking | JSON、XML解析
iOS开发教程之OC语言
width="728" height="90" frameborder="0" marginwidth="0" marginheight="0" vspace="0" hspace="0" allowtransparency="true" scrolling="no" allowfullscreen="true" id="aswift_0" name="aswift_0" style="left: 0px; position: absolute; top: 0px;">
查看评论

  暂无评论

发表评论
  • 用 户 名:
  • qq_33573235
  • 评论内容:
  • 插入代码
  •   
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
  • 个人资料
  •  
    4
    • 访问:77091次
    • 积分:1413
    • 等级: 
    • 排名:千里之外
    • 原创:52篇
    • 转载:4篇
    • 译文:1篇
    • 评论:40条
  • 最新评论
id="iframeu2734128_0" src="http://pos.baidu.com/xcsm?sz=200x200&rdid=2734128&dc=2&exps=113010&di=u2734128&dri=0&dis=0&dai=2&ps=3552x299&coa=at%3D3%26rsi0%3D200%26rsi1%3D200%26pat%3D6%26tn%3DbaiduCustNativeAD%26rss1%3D%2523FFFFFF%26conBW%3D1%26adp%3D1%26ptt%3D0%26titFF%3D%2525E5%2525BE%2525AE%2525E8%2525BD%2525AF%2525E9%25259B%252585%2525E9%2525BB%252591%26titFS%3D%26rss2%3D%2523000000%26titSU%3D0%26ptbg%3D90%26piw%3D0%26pih%3D0%26ptp%3D0&dcb=BAIDU_SSP_define&dtm=HTML_POST&dvi=0.0&dci=-1&dpt=none&tsr=0&tpr=1472033949900&ti=google%20protobuf%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0%E4%BA%8C%EF%BC%9A%E4%BD%BF%E7%94%A8%E5%92%8C%E5%8E%9F%E7%90%86%20-%20majianfei1023%E7%9A%84%E4%B8%93%E6%A0%8F%20-%20%E5%8D%9A%E5%AE%A2%E9%A2%91%E9%81%93%20-%20CSDN.&ari=2&dbv=2&drs=3&pcs=1798x772&pss=1799x5819&cfv=0&cpl=33&chi=1&cce=true&cec=UTF-8&tlm=1472033949&rw=772&ltu=http%3A%2F%2Fblog.csdn.net%2Fmajianfei1023%2Farticle%2Fdetails%2F45112415&ltr=http%3A%2F%2Fblog.csdn.net%2Fmajianfei1023%2Farticle%2Fdetails%2F45371743&ecd=1&psr=1366x768&par=1366x728&pis=-1x-1&ccd=24&cja=true&cmi=59&col=zh-CN&cdo=-1&tcn=1472033950&qn=2e22686a591188a4&tt=1472033949876.31.219.439" width="200" height="200" align="center,center" vspace="0" hspace="0" marginwidth="0" marginheight="0" scrolling="no" frameborder="0" allowtransparency="true" style="border-width: 0px; border-style: initial; vertical-align: bottom; margin: 0px;">


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值