本文主要会介绍怎么使用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. Loadrunner参数化逗号报错解决方法

    Loadrunner参数化逗号报错解决方法     介绍Loadrunner参数化时,参数中包含有逗号时出错的解决方法. 在Loadrunner进行参数化时,参数中如果含有逗号,编辑保存后会报错: 此 ...

  2. LoadRunner中的随机数

    LoadRunner中的随机数 Action() { int i; ]; srand(time(NULL)); i=rand()%; lr_save_datetime("%m%d%H%M%S ...

  3. babel使用中不想使用 严格模式 如何去除?

    使用babel进行es6转es5时,默认转化之后是严格模式,有些时候我们想去除严格模式. 解决方法如下 安装 babel-plugin-transform-remove-strict-mode 依赖 ...

  4. poj1258 Agri-Net(Prime || Kruskal)

    题目链接 http://poj.org/problem?id=1258 题意 有n个农场,现在要在n个农场之间铺设光纤使得n个农场连接起来,求铺设光纤的最短距离. 思路 最小生成树问题,使用Prime ...

  5. Bootstrap进阶五:Web开发中很实用的交互效果积累

    1.页面切换效果 我们已经在示例中罗列了一组动画,可以被应用到页面切换过程中,创造出很有趣的导航效果.  2.视差滚动(parallax-slider) 视差滚动(parallax-slider)已 ...

  6. CodeForces - 620C Pearls in a Row 贪心 STL

    C. Pearls in a Row time limit per test 2 seconds memory limit per test 256 megabytes input standard ...

  7. Socket 编程之 TCP 实现

    前几天介绍了计算机网络的一些概念,并介绍了几个协议.下面就说说 Java 中的 Socket 编程,服务器和客户端是如何通信的呢? 首先要介绍一下 Socket ,我们知道在 TCP/IP 协议簇中, ...

  8. Django一些开发经验

    总结一些 Django 开发的小经验.先说一些最最基础的吧. 使用 virtualenv 隔离开发环境 使用 pip 管理项目依赖,主要就是一个小技巧,使用 pip freeze > requi ...

  9. python 列表的浅拷贝和深拷贝

    转自:https://www.cnblogs.com/laolibk/p/7821369.html 浅拷贝 shallow copy 和深拷贝 deep copy list.copy() 浅拷贝:复制 ...

  10. requests爬取百度音乐

    使用requests爬取百度音乐,我想把当前热门歌手的音乐信息爬下来. 首先进行url分析,可以看到: 歌手网页: 薛之谦网页: 可以看到,似乎这些路劲的获取一切都很顺利,然后可以写代码: # -*- ...