ProtoBuf练习(一)

基础数据类型

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;
}
posted @ 2018-05-25 11:20  银魔术师  阅读(587)  评论(0编辑  收藏  举报