本文主要会介绍怎么使用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. 解决ssh登陆过慢问题

    我们经常会遇到的一个情况是telnet到server速度很快,但是ssh连接的时候却很慢,大概要等半分钟甚至更久.ping的速度也非常好,让人误以为是ssh连接不上. 下面说下如何解决这样的问题,最为 ...

  2. sql结合通配符来自定义转义字符

    1.使用   ESCAPE   关键字,定义转义符.在模式中,当转义符置于通配符之前时,该通配符就解释为普通字符.例如,要搜索在任意位置包含字符串   5%   的字符串,请使用:      WHER ...

  3. loadrunner——常见函数

    loadrunner——常见函数 分类: LoadRunner 2012-04-11 20:41 703人阅读 评论(0) 收藏 举报 loadrunnersearchweb服务器脚本stringwe ...

  4. MemSQL Start[c]UP 2.0 - Round 1 F - Permutation 思维+线段树维护hash值

    F - Permutation 思路:对于当前的值x, 只需要知道x + k, x - k这两个值是否出现在其左右两侧,又因为每个值只有一个, 所以可以转换成,x+k, x-k在到x所在位置的时候是否 ...

  5. CIDR的IP地址的表示与划分方法

    早期的ip地址划分: 最初设计互联网络时,为了便于寻址以及层次化构造网络,每个IP地址包括两个标识码(ID),即网络ID和主机ID.同一个物理网络上的所有主机都使用同一个网络ID,网络上的一个主机(包 ...

  6. 《Android源码设计模式》--享元模式

    No1: 享元模式是对象池的一种实现.享元模式用来尽可能减少内存使用量,它适合用于可能存在大量重复对象的场景,来缓存可共享的对象,达到对象共享.避免创建过多对象的效果,这样一来就可以提升性能.避免内存 ...

  7. 使用IDEA和Maven创建Javaweb项目

    1.File -- New -- Project

  8. JavaQuery选择器

    1.基本选择器 <!DOCTYPE html>   <html>   <head lang="en">   <meta charset=& ...

  9. mysql查询语句 和 多表关联查询 以及 子查询

    原文地址: http://blog.csdn.net/github_37767025/article/details/67636061 1.查询一张表: select * from 表名: 2.查询指 ...

  10. android view的 绘制流程

    韩梦飞沙  韩亚飞  313134555@qq.com  yue31313  han_meng_fei_sha 首先是 从  视图根 这个类的  进行遍历 performTraversals 方法 开 ...