Google Protocol Buffers浅析(三)


Google Protocol Buffers浅析(三)
2010年11月02日
  本文主要会介绍怎么使用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("[email protected]"); personMe->set_unsure("19bf173a0e87ab"); //第二个联系人的数据定义与初始化 Person *personHim = addressBook.add_person(); personHim->set_id(2); personHim->set_name("XXX"); personHim->set_email("[email protected]"); 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);    很容易看出,上述代码即在地址簿中添加了俩个联系人,然后又分别填充各个联系人的数据信息,通过上述代码一个地址簿的数据便准备好了。
  二、序列化数据  
  其实通过看编译器生成的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)) { cerrC库中的文件操作函数,可以更方便的定制输出文件。
  3)SerializeToCodedStream方式
  该方式主要指用到的google buffer的库中提供的一组数据流操作对象,在使用这些对象之前需要引入一些头文件,如下所示: #include  #include  #include  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等方式都应该比较类似,所以感兴趣的朋友可以自己动手试试。   
  下篇文章再稍微介绍下反序列化的方法,但是应该不会太多内容,毕竟都方法都很相似。
  欢迎转载,转载时请务必保留原文出处: http://www.cnblogs.com/royenhome ,谢谢合作!

猜你喜欢

转载自wjqcx29o.iteye.com/blog/1364690