1. 程式人生 > >ProtoBuf練習(一)

ProtoBuf練習(一)

CA sage return scala 源文件 locate 如果 fixed ims

基礎數據類型

protobuf語言的基礎字段類型相當於C++語言的基礎類型

工程目錄結構

$ ls proto/
TFixed.proto  TInt.proto  TScalar.proto  TStr.proto

proto文件

$ cat TScalar.proto
syntax = "proto3";

//導入其他message
import "TInt.proto";
import "TFixed.proto";
import "TStr.proto";

//使用其他message作為字段類型,如果message使用了package則需要使用package.的方式引用
message TScalar {
    scalar.TInt int_val = 1;
    TFixed fixed_val = 2;
    TStr str_val = 3;
};

$ cat TInt.proto
syntax = "proto3";

// 設置包名,在生成的C++源碼中將變成namespace
package scalar;

message TInt {
    double ddouble_val = 1;
    float float_val = 2;
    int32 int32_val = 3;
    uint32 uint32_val = 4;
    sint32 sint32_val = 5;
    bool bool_val = 6;
};

$ cat TFixed.proto
syntax = "proto3";

message TFixed {
    fixed32 fixed32_val = 1;
    fixed64 fixed64_val = 2;
    sfixed32 sfixed32_val = 3;
    sfixed64 sfixed64_val = 4;
};

$ cat TStr.proto
syntax = "proto3";

message TStr {
    string string_val = 1;
    bytes bytes_val = 2;
};

讀寫源文件

$ cat writer.cpp
#include <fstream>
#include <iostream>
#include "TScalar.pb.h"

using namespace std;

int main(int argc, char *argv[])
{
    TScalar msg;
    scalar::TInt* iMsg = new scalar::TInt();
    TFixed* fMsg = new TFixed();
    TStr* sMsg = new TStr();
    // 使用protobuf自己的內存管理
    msg.set_allocated_int_val(iMsg);
    msg.set_allocated_fixed_val(fMsg);
    msg.set_allocated_str_val(sMsg);

    iMsg->set_ddouble_val(11.01);
    iMsg->set_float_val(11.01);
    iMsg->set_int32_val(-1);
    iMsg->set_uint32_val(1);
    iMsg->set_sint32_val(-1);
    iMsg->set_bool_val(true);

    fMsg->set_fixed32_val(1);
    fMsg->set_fixed64_val(1);
    fMsg->set_sfixed32_val(-1);
    fMsg->set_sfixed64_val(-1);

    sMsg->set_string_val("中");
    sMsg->set_bytes_val("文");

    fstream output("./log", ios::out | ios::trunc | ios::binary);
    cout << "Serialize start." << endl;
    if (!msg.SerializeToOstream(&output))
        {
                cout << "Serialize failed." << endl;
                return -1;
        }
    output.close();
    cout << "Serialize end." << endl;
    return 0;
}

$ cat reader.cpp
#include <fstream>
#include <iostream>
#include "TScalar.pb.h"

using namespace std;

int main(int argc, char *argv[])
{
    fstream input("./log", ios::in | ios::binary);
    cout << "Deserialize start." << endl;

    TScalar msg;
    //如果writer依次寫入TInt、TFixed、TStr,然後在reader依次讀取TInt、TFixed、TStr,這時只有第一個message能正常解析,後兩條message解析失敗,因為ParseFromIstream會一次性把input流內容讀完,導致後面的message解析時讀取的輸入流已經為空,所以表面上看起來就好像protocol buffer只能序列化和反序列化一條message
    if (!msg.ParseFromIstream(&input))
    {
        cout << "Deserialize failed." << endl;
        return -1;
    }
    msg.int_val().PrintDebugString();
    msg.fixed_val().PrintDebugString();
    msg.str_val().PrintDebugString();

    cout << "Deserialize end." << endl;
    input.close();
    return 0;
}

ProtoBuf練習(一)