小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

Google Protocol Buffers淺析(三)

 feng0926 2013-08-06

     本文主要會(huì)介紹怎么使用Google Protocol的Lib來序列化我們的數(shù)據(jù),方法很多種,本文只介紹其中的三種,其他的方法讀者可以通過自行研究摸索。但總的來說,序列化數(shù)據(jù)總的來說分為以下倆步:

     1)使用數(shù)據(jù)源填充數(shù)據(jù)結(jié)構(gòu),無論數(shù)據(jù)源來自文件還是內(nèi)存還是標(biāo)準(zhǔn)輸入

     2)利用Lib提供的序列化接口將數(shù)據(jù)結(jié)構(gòu)序列化,然后存儲(chǔ)在內(nèi)存或者磁盤上

    

     一、填充數(shù)據(jù)結(jié)構(gòu) 

     從數(shù)據(jù)源中獲取數(shù)據(jù),這兒的數(shù)據(jù)源可能來自磁盤上的一個(gè)文件或者內(nèi)存中存儲(chǔ)的一段數(shù)據(jù)或者來自標(biāo)準(zhǔn)輸入的數(shù)據(jù)。我們需要做的就是,將AddressBook這個(gè)數(shù)據(jù)結(jié)構(gòu)中的各個(gè)字段填充。本例中是通過AddressBook提供的add_person函數(shù)來獲得一個(gè)Person的指針,從而對(duì)其進(jìn)行填充,如下代碼所示: 

復(fù)制代碼
    //地址簿數(shù)據(jù)定義
    AddressBook    addressBook;            
    
    
//第一個(gè)聯(lián)系人的數(shù)據(jù)定義與初始化
    Person    *personMe  = addressBook.add_person();
    personMe
->set_id(1);
    personMe
->set_name("royen");    
    personMe
->set_email("zwg19891129@163.com");
    personMe
->set_unsure("19bf173a0e87ab");
    
    
//第二個(gè)聯(lián)系人的數(shù)據(jù)定義與初始化
    Person  *personHim = addressBook.add_person();
    personHim
->set_id(2);
    personHim
->set_name("XXX");
    personHim
->set_email("XXX@XXX.com");
    personHim
->set_unsure("19bf173a0e87ab");
    
    
//personMe的手機(jī)號(hào)碼數(shù)據(jù)定義與初始化
    Person_PhoneNumber *phoneNumberMobile = personMe->add_phone();
    phoneNumberMobile
->set_number("15996110120");
    phoneNumberMobile
->set_type(Person_PhoneType_MOBILE);
        
    
//personMe的座機(jī)號(hào)碼數(shù)據(jù)定義與初始化
    Person_PhoneNumber *phoneNumberHome   = personMe->add_phone();
    phoneNumberHome
->set_number("0256110120");
    phoneNumberHome
->set_type(Person_PhoneType_HOME);

    
//personHim的一個(gè)號(hào)碼數(shù)據(jù)定義與初始化
    Person_PhoneNumber *phoneNumberHim      = personHim->add_phone();
    phoneNumberHim
->set_number("15996111111");    
    phoneNumberHim
->set_type(Person_PhoneType_HOME);
復(fù)制代碼

         很容易看出,上述代碼即在地址簿中添加了倆個(gè)聯(lián)系人,然后又分別填充各個(gè)聯(lián)系人的數(shù)據(jù)信息,通過上述代碼一個(gè)地址簿的數(shù)據(jù)便準(zhǔn)備好了。

        

        二、序列化數(shù)據(jù) 

        其實(shí)通過看編譯器生成的AddressBook這個(gè)類所提供的方法名,既可以大致知道有哪些序列化的方式,如下所示:

         

        從上圖可以看出,可利用序列化的方法很多,本文中主要使用SerializeToString、SerializeToCodedStream以及SerializeToOstream來完成序列化。 

        下面就分別就這幾種方式來介紹下:

        1) SerializeToCodedStream方式

        首先可以知道該函數(shù)的原型是bool SerializeToCodedStream(std::ostream *),所以使用該函數(shù)需要結(jié)合C++的fstream流,代碼如下:         

復(fù)制代碼
    //方法一: 使用SerializePartialToOstream來序列化,注意ios::binary以二進(jìn)制流寫入文件
    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();
復(fù)制代碼

          可以看出,采用這種方法相當(dāng)?shù)谋憬荩乙埠芎?jiǎn)潔,但有個(gè)缺點(diǎn)就是輸出到文件的編碼格式不好控制,所以可以使用下面介紹的這種方法。

         

       2)SerializeToString方式

       函數(shù)原型為bool SerializeToString(std::string* output) ,所以可以講填充在數(shù)據(jù)結(jié)構(gòu)AddressBook中的數(shù)據(jù)取出存到一個(gè)string對(duì)象中,然后再以二進(jìn)制流的方式將其寫入到磁盤文件中,代碼如下:               

復(fù)制代碼
    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;
    }
 
復(fù)制代碼

       上述代碼稍微繁瑣了點(diǎn),但是也是一種序列化的方式,通過結(jié)合使用C庫中的文件操作函數(shù),可以更方便的定制輸出文件。

  

       3)SerializeToCodedStream方式

       該方式主要指用到的google buffer的庫中提供的一組數(shù)據(jù)流操作對(duì)象,在使用這些對(duì)象之前需要引入一些頭文件,如下所示:       

   #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;

       該方式也結(jié)合C庫的open與write函數(shù),序列化部分的代碼如下:               

復(fù)制代碼
    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);    
復(fù)制代碼

        本文暫時(shí)介紹這三種序列化話方式,還有像SerializeToArray以及SerializeToFileDescriptor等方式都應(yīng)該比較類似,所以感興趣的朋友可以自己動(dòng)手試試。   

        下篇文章再稍微介紹下反序列化的方法,但是應(yīng)該不會(huì)太多內(nèi)容,畢竟都方法都很相似。

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多