google protocol buffer的原理和使用(二)
本文主要会介绍怎么使用Google Protocol的Lib来序列化我们的数据,方法非常多种,本文仅仅介绍当中的三种。其它的方法读者能够通过自行研究摸索。但总的来说,序列化数据总的来说分为下面俩步:
1)使用数据源填充数据结构,不管数据源来自文件还是内存还是标准输入
2)利用Lib提供的序列化接口将数据结构序列化,然后存储在内存或者磁盘上
一、填充数据结构
从数据源中获取数据。这儿的数据源可能来自磁盘上的一个文件或者内存中存储的一段数据或者来自标准输入的数据。我们须要做的就是,将AddressBook这个数据结构中的各个字段填充。本例中是通过AddressBook提供的add_person函数来获得一个Person的指针,从而对其进行填充,例如以下代码所看到的:
//地址簿数据定义
AddressBook addressBook;
//第一个联系人的数据定义与初始化
Person *personMe = addressBook.add_person();
personMe->set_id(1);
personMe->set_name("royen");
personMe->set_email("zwg19891129@163.com");
personMe->set_unsure("19bf173a0e87ab");
//第二个联系人的数据定义与初始化
Person *personHim = addressBook.add_person();
personHim->set_id(2);
personHim->set_name("XXX");
personHim->set_email("XXX@XXX.com");
personHim->set_unsure("19bf173a0e87ab");
//personMe的手机号码数据定义与初始化
Person_PhoneNumber *phoneNumberMobile = personMe->add_phone();
phoneNumberMobile->set_number("15996110120");
phoneNumberMobile->set_type(Person_PhoneType_MOBILE);
//personMe的座机号码数据定义与初始化
Person_PhoneNumber *phoneNumberHome = personMe->add_phone();
phoneNumberHome->set_number("0256110120");
phoneNumberHome->set_type(Person_PhoneType_HOME);
//personHim的一个号码数据定义与初始化
Person_PhoneNumber *phoneNumberHim = personHim->add_phone();
phoneNumberHim->set_number("15996111111");
phoneNumberHim->set_type(Person_PhoneType_HOME);
非常easy看出,上述代码即在地址簿中加入了俩个联系人。然后又分别填充各个联系人的数据信息,通过上述代码一个地址簿的数据便准备好了。
二、序列化数据
事实上通过看编译器生成的AddressBook这个类所提供的方法名,既能够大致知道有哪些序列化的方式。例如以下所看到的:
从上图能够看出。可利用序列化的方法非常多,本文中主要使用SerializeToString、SerializeToCodedStream以及SerializeToOstream来完毕序列化。
以下就分别就这几种方式来介绍下:
1) SerializeToCodedStream方式
首先能够知道该函数的原型是bool SerializeToCodedStream(std::ostream *),所以使用该函数须要结合C++的fstream流。代码例如以下:
//方法一: 使用SerializePartialToOstream来序列化,注意ios::binary以二进制流写入文件
fstream fserial("addressbook.data",ios::out | ios::trunc | ios::binary);
if (!addressBook.SerializePartialToOstream(&fserial))
{
cerr<<"Failed to serial address book data!\n";
return;
}
cout<<"Serial address book data successfully!\n";
fserial.close();
fserial.clear();
能够看出,採用这样的方法相当的便捷,并且也非常简洁,但有个缺点就是输出到文件的编码格式不好控制,所以能够使用以下介绍的这样的方法。
2)SerializeToString方式
函数原型为bool SerializeToString(std::string* output) ,所以能够讲填充在数据结构AddressBook中的数据取出存到一个string对象中,然后再以二进制流的方式将其写入到磁盘文件里。代码例如以下:
FILE *g_AddressBook = fopen("addressbook.data","wb,ccs = UNICODE");
if( NULL == g_AddressBook )
{
cerr<<"Create addressbook.data failed!\n";
return ;
}
string serialStream = "";
if( !addressBook.SerializePartialToString(&serialStream) )
{
cerr<<"Failed to serial addressbook data!\n";
return;
}
fwrite( serialStream.c_str(),sizeof(char),addressBook.ByteSize(),g_AddressBook);
cout<<"serial address successfully!\n";
if( g_AddressBook )
{
fclose(g_AddressBook);
g_AddressBook = NULL;
}
上述代码略微繁琐了点。可是也是一种序列化的方式。通过结合使用C库中的文件操作函数,能够更方便的定制输出文件。
3)SerializeToCodedStream方式
该方式主要指用到的google buffer的库中提供的一组数据流操作对象。在使用这些对象之前须要引入一些头文件。例如以下所看到的:
#include <google/protobuf/io/zero_copy_stream_impl.h>
#include <google/protobuf/io/zero_copy_stream.h>
#include <google/protobuf/io/coded_stream.h>
using namespace::google::protobuf::io;
该方式也结合C库的open与write函数,序列化部分的代码例如以下:
int fd = _open("addressbook.data", _O_WRONLY |_O_CREAT| _O_BINARY, _S_IREAD|_S_IWRITE);
if( -1 == fd )
{
cerr<<"Create addressbook.data failed!\n";
return ;
}
char tmpArr[MAX_SIZE];
memset(tmpArr,0,sizeof(tmpArr));
ZeroCopyOutputStream *raw_output = new ArrayOutputStream(tmpArr,addressBook.ByteSize()+1);
CodedOutputStream* coded_output = new CodedOutputStream(raw_output);
if( !addressBook.SerializeToCodedStream( coded_output ))
{
cerr<<"Fail to serial addressbook data!\n";
return;
}
_write(fd,tmpArr,addressBook.ByteSize()+1);
cout<<"serial address successfully!\n";
delete coded_output;
delete raw_output;
close(fd);
本文临时介绍这三种序列化话方式,还有像SerializeToArray以及SerializeToFileDescriptor等方式都应该比較类似。所以感兴趣的朋友能够自己动手试试。
google protocol buffer的原理和使用(二)的更多相关文章
- google protocol buffer的原理和使用(一)
一.简单的介绍 Protocol buffers是一个用来序列化结构化数据的技术,支持多种语言诸如C++.Java以及Python语言.能够使用该技术来持久化数据或者序列化成网络传输的数据. ...
- google protocol buffer的原理和使用(三)
介绍下怎么反序列化GoogleBuffer数据.并在最后提供本系列文章中所用到的代码整理供下载. 上一篇文章介绍了如何将数据序列化到了addressbook.data中.那么对于接受方而言该怎么解析出 ...
- google protocol buffer的原理和使用(四)
有个电子商务的系统(如果用C++实现).当中的模块A须要发送大量的订单信息给模块B.通讯的方式使用socket. 如果订单包含例如以下属性: ----------------------------- ...
- Google Protocol Buffer 的使用和原理
Google Protocol Buffer 的使用和原理 Protocol Buffers 是一种轻便高效的结构化数据存储格式,可以用于结构化数据串行化,很适合做数据存储或 RPC 数据交换格式.它 ...
- 转Google Protocol Buffer 的使用和原理
Google Protocol Buffer 的使用和原理 Protocol Buffers 是一种轻便高效的结构化数据存储格式,可以用于结构化数据串行化,很适合做数据存储或 RPC 数据交换格式.它 ...
- Google Protocol Buffer 的使用(二)
一.protobuf应用场景 protobuf 在Java中的应用场景可以是序列化和反序列化,流可以通过文件或者通过网络TCP/UDP等方式传输.新建一个.proto文件 syntax = " ...
- Google Protocol Buffer 的使用和原理[转]
本文转自: http://www.ibm.com/developerworks/cn/linux/l-cn-gpb/ Protocol Buffers 是一种轻便高效的结构化数据存储格式,可以用于结构 ...
- Google Protocol Buffer 的使用和原理(无论对存储还是数据交换,都是个挺有用的东西,有9张图做说明,十分清楚)
感觉Google Protocol Buffer无论对存储还是数据交换,都是个挺有用的东西,这里记录下,以后应该用得着.下文转自: http://www.ibm.com/developerworks/ ...
- (转)Google Protocol Buffer 的使用和原理
转自:https://www.ibm.com/developerworks/cn/linux/l-cn-gpb/index.html 简介 什么是 Google Protocol Buffer? ...
随机推荐
- 黑马程序员_java基础笔记(06)...集合
—————————— ASP.Net+Android+IOS开发..Net培训.期待与您交流! —————————— JavaApi(其实就是java给我们提供的已经定义好的对象.工具对象:集合框架) ...
- 004 Hadoop2.x基础知识
一:大数据应用 1.Cloudera cloudera公司是Hadoop三大发行商之一,其版本为CDH版本,现在最新的版本是CDH5. 网站:http://archive.cloudera.com/c ...
- thinkphp5.0返回插入数据id
添加数据后如果需要返回新增数据的自增主键,可以使用getLastInsID方法: Db::name('user')->insert($data); $userId = Db::name('use ...
- PHP 数组的添加和读取
在实际的开发中,会经常使用数组的添加和读取.这里把经常使用的操作记下来,以备以后查阅. <?php //一维数值数组 $list = array('wang','god'); $list[] = ...
- Python 学习经历分享
如果说 Java 是亲儿子的话,那么 Python 应该就是干儿子了.看了一下所有关于 Python 的笔记,我发现原来我在 4 月份的时候就已经涉足 Python 了,但是到目前为止才真正算做出了一 ...
- 转 SSM框架整合to萌新
作用: SSM框架是spring MVC ,spring和mybatis框架的整合,是标准的MVC模式,将整个系统划分为表现层,controller层,service层,DAO层四层 使用spring ...
- 学会使用DNSPod,仅需三步
学会使用DNSPod,仅需三步 第一步:在DNSPod添加记录 1.访问 https://www.dnspod.cn网站,在DNSPod官网首页的右上角,有[注册],如下图所示,点击[注册]按钮 ...
- hdu 1518 dfs+剪枝
题目大意:几根棒子能否组成一个正方形 Sample Input3 //测试组数4 1 1 1 1 //棒子数目以及每根棒子的长度5 10 20 30 40 508 1 7 2 ...
- Python文件类型
Python的文件类型分为三种:源代码.字节代码.优化代码. 1. 源代码 Python源代码文件,即py脚本文件,由 python.exe 解释,可在控制台下运行.pyw脚本文件是图形用户接口 ...
- Codeforces Round #280 (Div. 2) D. Vanya and Computer Game 预处理
D. Vanya and Computer Game time limit per test 2 seconds memory limit per test 256 megabytes input s ...