Yanyg - Software Engineer

Protobuf序列化与反序列化

目录

系统运行时生成的一些重要数据需要持久化到存储介质中。数据在进程内一般是 raw-data,这样处理方便快速。但raw-data以binary形式持久化到介质会普遍地导致系统兼容性问题和维护问题。将raw-data序列化为结构化数据保存,后续使用时再将结构化数据反序列化为raw-data是一种通用方式。

Protobuf(Protocol Buffers)是Google定义的一种结构化数据序列化/反序列化机制。类似XML,但生成数据占用长度更小。支持C++、Java、Python等多种语言。不支持C。Protobuf有良好的版本兼容性。

1 安装

~$ git clone https://github.com/protocolbuffers/protobuf.git
~$ cd protobuf
~$ git submodule update --init --recursive
~$ mkdir -p build && cd build && cmake ../cmake && make -j2 && sudo make install
~$ protoc --version
libprotoc 3.11.2

2 测试

写一个简单的proto文件common.proto:

syntax = "proto3";

package ads.common;

message Open
{
    string filename = 1;
    int32  flag = 3;
}

使用protoc生成C++文件:

~$ protoc -I. --cpp_out=. common.proto

在当前目录下生成common.pb.h和common.pb.cc。

C++ Example:

#include <fstream>
#include <iostream>
#include <sstream>
#include <string>

#include "common.pb.h"

using namespace std;

int main(int argc, char *argv[])
{
    GOOGLE_PROTOBUF_VERIFY_VERSION;

    ads::common::OpenPB openPB;
    openPB.set_filename("hello.txt");
    openPB.set_flag(1234);

    string data;
    openPB.SerializeToString(&data);
    cout<<"SerializeData:"<<endl
        <<"    data.length:"<<data.length()<<endl;

    ofstream wf("pb.txt");
    wf<<data;
    wf.close();

    ifstream rf("pb.txt");
    ostringstream rs;
    rs << rf.rdbuf();
    ads::common::OpenPB openPB2;
    openPB2.ParseFromString(rs.str());
    cout<<"DeserializeData:"<<endl
        <<"    filename:"<<openPB2.filename()<<endl
        <<"    flag    :"<<openPB2.flag()<<endl;

    return 0;
}

Compile and run:

yanyg@t430:~/tmp $ g++ example.cpp common.pb.cc -lprotobuf
yanyg@t430:~/tmp $ ./a.out
SerializeData:
    data.length:14
    data.value:
        hello.txt
DeserializeData:
    filename:hello.txt
    flag    :1234

3 Reference