本文主要会介绍怎么使用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. C++雾中风景7:闭包

    本来说好要聊一聊命名空间的,因为最近在看C++lambda表达式的内容,所以借这个机会我们来好好聊一聊C++的闭包. 1.什么是闭包? 闭包(closure)是函数式编程的重要的语法结构. 闭包的概念 ...

  2. Python 中的函数

    学了 Python 中的数据类型,语句,接下来就来说一下 Python 中的函数,函数是结构化编程的核心.我们使用函数可以增加程序的可读性.自定义函数时使用关键字def 函数由多条语句组成.在定义函数 ...

  3. springmvc遇见406错误的问题分析

    如果springmvc遇到406错误: 90%没有加入Jackson的包 10%因为后缀为.html 10%的情况,解决方案为加多一个映射,使用.action

  4. 【Performance】chrome调试面板

    本篇文章以chrome版本67.0.3396.99为例,说明性能方面的调试.

  5. leetcode 相交链表 python实现

    这道题 要想解决其实不难, 开两层循环进行遍历就能实现,但是会超时 如果想要O(n) 的时间复杂度, 我考虑用哈希表来存储遍历过的元素,如果发现当前遍历的元素在哈希表里,那说明交叉点就在这 这里利用了 ...

  6. python opencv3 运动检测

    git:https://github.com/linyi0604/Computer-Vision 思路:  开启摄像头后 设置一个当前帧为背景, 在之后检测到的帧都与背景对比不同,对不同的地方进行检测 ...

  7. 【UOJ #221】【NOI 2016】循环之美

    http://uoj.ac/problem/221 因为\(a\)和\(b\)不互质时,\(\frac ab=\frac{\frac a{(a,b)}}{\frac b{(a,b)}}\),所以只用求 ...

  8. POJ 3678 Katu Puzzle 2-SAT 强连通分量 tarjan

    http://poj.org/problem?id=3678 给m条连接两个点的边,每条边有一个权值0或1,有一个运算方式and.or或xor,要求和这条边相连的两个点经过边上的运算后的结果是边的权值 ...

  9. hdu 5288 OO’s Sequence(2015多校第一场第1题)枚举因子

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5288 题意:在闭区间[l,r]内有一个数a[i],a[i]不能整除 除去自身以外的其他的数,f(l,r ...

  10. Codeforces Round #222 (Div. 1) B. Preparing for the Contest 二分+线段树

    B. Preparing for the Contest 题目连接: http://codeforces.com/contest/377/problem/B Description Soon ther ...