本文主要会介绍怎么使用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的原理和使用(二)的更多相关文章

  1. google protocol buffer的原理和使用(一)

    一.简单的介绍      Protocol buffers是一个用来序列化结构化数据的技术,支持多种语言诸如C++.Java以及Python语言.能够使用该技术来持久化数据或者序列化成网络传输的数据. ...

  2. google protocol buffer的原理和使用(三)

    介绍下怎么反序列化GoogleBuffer数据.并在最后提供本系列文章中所用到的代码整理供下载. 上一篇文章介绍了如何将数据序列化到了addressbook.data中.那么对于接受方而言该怎么解析出 ...

  3. google protocol buffer的原理和使用(四)

    有个电子商务的系统(如果用C++实现).当中的模块A须要发送大量的订单信息给模块B.通讯的方式使用socket. 如果订单包含例如以下属性: ----------------------------- ...

  4. Google Protocol Buffer 的使用和原理

    Google Protocol Buffer 的使用和原理 Protocol Buffers 是一种轻便高效的结构化数据存储格式,可以用于结构化数据串行化,很适合做数据存储或 RPC 数据交换格式.它 ...

  5. 转Google Protocol Buffer 的使用和原理

    Google Protocol Buffer 的使用和原理 Protocol Buffers 是一种轻便高效的结构化数据存储格式,可以用于结构化数据串行化,很适合做数据存储或 RPC 数据交换格式.它 ...

  6. Google Protocol Buffer 的使用(二)

    一.protobuf应用场景 protobuf 在Java中的应用场景可以是序列化和反序列化,流可以通过文件或者通过网络TCP/UDP等方式传输.新建一个.proto文件 syntax = " ...

  7. Google Protocol Buffer 的使用和原理[转]

    本文转自: http://www.ibm.com/developerworks/cn/linux/l-cn-gpb/ Protocol Buffers 是一种轻便高效的结构化数据存储格式,可以用于结构 ...

  8. Google Protocol Buffer 的使用和原理(无论对存储还是数据交换,都是个挺有用的东西,有9张图做说明,十分清楚)

    感觉Google Protocol Buffer无论对存储还是数据交换,都是个挺有用的东西,这里记录下,以后应该用得着.下文转自: http://www.ibm.com/developerworks/ ...

  9. (转)Google Protocol Buffer 的使用和原理

    转自:https://www.ibm.com/developerworks/cn/linux/l-cn-gpb/index.html   简介 什么是 Google Protocol Buffer? ...

随机推荐

  1. Redis的安装与部署(CentOS6.5)

    一.下载安装包 wget http://redis.googlecode.com/files/redis-2.4.5.tar.gz 二.编译源程序 tar -zxvf redis-2.4.5.tar. ...

  2. read()函数的困惑

    #define BUF_SIZE 10 int main() { int cnt; char buf[BUF_SIZE]; cnt = read(STDIN_FILENO, buf, BUF_SIZE ...

  3. 图形文件元数据管理工具exiv2

    图形文件元数据管理工具exiv2   图形文件通常都包含多种元数据,如Exif.IPTC.XMP.这些信息往往是渗透人员收集的目标.为了便于管理这些信息,Kali Linux内置了专用工具exiv2. ...

  4. PHP-FPM高负载的解决办法

    =================== 优化设置 ========================= When you running a highload website with PHP-FPM ...

  5. 最新OFFICE 0day漏洞分析

    漏洞概述 fireeye最近公布了一个OFFICE 0day,在无需用户交互的情况下,打开word文档就可以通过hta脚本执行任意代码.经过研究发现,此漏洞的成因主要是word在处理内嵌OLE2LIN ...

  6. PHP渗透中的奇淫技巧--检查相等时的漏洞

    PHP是现在网站中最为常用的后端语言之一,是一种类型系统 动态.弱类型的面向对象式编程语言.可以嵌入HTML文本中,是目前最流行的web后端语言之一,并且可以和Web Server 如apache和n ...

  7. hdu 4545 贪心 *

    题意:小明和他的好朋友小西在玩一个新的游戏,由小西给出一个由小写字母构成的字符串,小明给出另一个比小西更长的字符串,也由小写字母组成,如果能通过魔法转 换使小明的串和小西的变成同一个,那么他们两个人都 ...

  8. maven -- 问题解决(一)解决eclipse中maven项目配置过程和maven install时出现的问题

    问题一: 配置项目时出现的错误: error: Cannot change version of project facet Dynamic Web Module to 2.5. error: One ...

  9. ZeptoLab Code Rush 2015 B. Om Nom and Dark Park DFS

    B. Om Nom and Dark Park Time Limit: 1 Sec  Memory Limit: 256 MB 题目连接 http://codeforces.com/contest/5 ...

  10. hadoop 2.7.1 高可用安装部署

    hadoop集群规划 目标:创建2个NameNode,做高可用,一个NameNode挂掉,另一个能够启动:一个运行Yarn,3台DataNode,3台Zookeeper集群,做高可用. 在hadoop ...