Protobuf(google protocol buffer)

Protobuf(google protocol buffer)

一、 简介

Google Protocol Buffer( 简称 Protobuf) 是 Google 公司内部的混合语言数据标准,目前已经正在使用的有超过 48,162 种报文格式定义和超过 12,183 个 .proto 文件。他们用于 RPC 系统和持续数据存储系统。
Protocol Buffers 是一种轻便高效的结构化数据存储格式,可以用于结构化数据串行化,或者说序列化。它很适合做数据存储或 RPC 数据交换格式。可用于通讯协议、数据存储等领域的语言无关、平台无关、可扩展的序列化结构数据格式。官方提供了 C++、Java、Python、go、c # 五种语言的 API,因为开源所以其他语言也相继有了支持。详情可查看

二、 安装

环境:Ubuntu 15.04
直接下载安装包,解压后编译安装:
下载地址:站点1,或者站点2
解压:tar –xzvf protobuf-3.0.0-beta-3.tar.gz
安装依赖工具:
sudo apt-get install autoconf automake libtool curl make g++ unzip
编译安装[4]:
./autogen.sh
./configure
make check
sudo make install
sudo ldconfig # refresh shared library cache.

三、 例子程序
3.1 Google官方例子[1]

1 . 编写文件addressbook.proto

//syntax = "proto2";

package tutorial;

message Person {
    required string name = 1;
    required int32 id = 2;
    optional string email = 3;

    enum PhoneType {
        MOBILE = 0;
        HOME = 1;
        WORK = 2;
    }

    message PhoneNumber {
        required string number = 1;
        optional PhoneType phone_type = 2 [default = HOME];
    }

    repeated PhoneNumber phone = 4;
}

message AddressBook {
    repeated Person person = 1; 
}

2 . 编译生成头文件和实现文件
protoc –I=./ --cpp_out=./ ./addressbook.proto

3 . 文件writer.cc

 /**
  * @file    writer.cc
  * @author  Home Jang(generalibm@gmail.com)
  * @date    2016-06-12 19:52:22
  */

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

#include "addressbook.pb.h"

using namespace std;

void PromptForAddress(tutorial::Person * person) {
    cout << "Enter person ID name :";
    int id;
    cin >> id;
    person->set_id(id);
    cin.ignore(256, '\n');

    cout << "Enter name:";
    getline(cin , *person->mutable_name());

    cout << "Enter email address (blank for none):";
    string email;
    getline(cin, email);
    if (!email.empty()) {
        person->set_email(email);
    }

    while (true) {
        cout << "Enter a phone number (or leave a blank to finish):";
        string number;
        getline(cin, number);
        if (number.empty()) {
            break;
        }

        tutorial::Person::PhoneNumber * phone_number = person->add_phone();
        phone_number->set_number(number);

        cout << "Is this a mobile, home or work phone?";
        string type;
        getline(cin, type);
        if ("mobile" == type) {
            phone_number->set_phone_type(tutorial::Person::MOBILE);
        } else if ("home" == type) {
            phone_number->set_phone_type(tutorial::Person::HOME);
        } else if ("work" == type) {
            phone_number->set_phone_type(tutorial::Person::WORK);
        } else {
            cout << "Unknow phone type." << endl;
        }// end else

    }// end while
}

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

    if (argc != 2) {
        cerr << "Usage :" << argv[0] << "ADDRESS_BOOK_FILE" << endl;
        return -1;
    }

    tutorial::AddressBook address_book;
    {
        fstream input(argv[1], ios::in | ios::binary);
        if (!input) {
            cout << argv[1] << ":File not found. Creating a new file." << endl;
        } else if (!address_book.ParseFromIstream(&input)) {
            cerr << "Failed to parse address book." << endl;
            return -1;
        }
    }

    // Add an address.
    PromptForAddress(address_book.add_person()); 

    {
        // Write the new address book back to disk.
        fstream output(argv[1], ios::out | ios::trunc | ios::binary);
        if (!address_book.SerializeToOstream(&output)) {
            cerr << "Failed to write address book." << endl;
            return -1;
        }//end if
    }

    // Delete all global objects allocated by libprotobuf.
    google::protobuf::ShutdownProtobufLibrary();

    return 0;
}

4 . 文件reader.cc

 /**
  * @file    reader.cc
  * @author  Home Jang(generalibm@gmail.com)
  * @date    2016-06-13 00:26:43
  */

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

#include "addressbook.pb.h"

using namespace std;

void ListPeople(const tutorial::AddressBook & address_book) {
    for (int i = 0; i < address_book.person_size(); i++) {
        const tutorial::Person & person = address_book.person(i);

        cout << " Person ID: " << person.id() << endl;
        cout << " Name : " << person.name() << endl;
        if (person.has_email()) {
            cout << " Email : " << person.email() << endl;
        }

        for (int j = 0; j < person.phone_size(); j++) {
            const tutorial::Person::PhoneNumber & phone_number = person.phone(j);

            switch (phone_number.phone_type()) {
                case tutorial::Person::MOBILE:
                    cout << " MOBILE : ";
                    break;
                case tutorial::Person::HOME:
                    cout << " HOME : ";
                    break;
                case tutorial::Person::WORK:
                    cout << " WORK : ";
                    break;
            }

            cout << phone_number.number() << endl;
        }

    }// end for
}



int main(int argc, char *argv[])
{
    //::GOOGLE::PROTOBUF_VERIFY_VERSION;

    if (argc != 2) {
        cerr << "Usage: " << argv[0] << " ADDRESS_BOOK_FILE" << endl;
        return -1;
    }   
    tutorial::AddressBook address_book;

    {
        fstream input(argv[1], ios::in | ios::binary);
        if (!address_book.ParseFromIstream(&input)) {
            cerr << "Failed to parse address book." << endl;
            return -1;
        }
    }

    ListPeople(address_book);

    google::protobuf::ShutdownProtobufLibrary();

    return 0;
}

5 . 编译
g++ -o writer writer.cc addressbook.pb.cc –lprotobuf
g++ -o reader reader.cc addressbook.pb.cc –lprotobuf
6 . 执行结果
./writer mid_file
$Enter person ID name :1001
$Enter name :Yun Ma
$Enter email address (blank for none):ali@ali.com
$Enter a phone number (or leave a blank to finish):17088888888
$Is this a mobile , home or work phone?work

./reader mid_file
Person ID :1001
Name : Yun MA
Email : ali@ali.com
WORK : work

3.2 DIY简单helloworld例子[3]

1.编写lm.helloworld.proto文件

syntax = "proto2";

package lm;

message helloworld {
    required int32      id = 1;
    required string     str = 2;
    optional int32      opt = 3;
}

2.编译生成头文件及相应实现文件

protoc -I=./ --cpp_out=./ ./lm.helloword.proto

3.编写writer.cc

 /**
  * @file    writer.cc
  * @author  Home Jang(generalibm@gmail.com)
  * @date    2016-06-13 16:04:02
  */

#include <iostream>
#include <fstream>

#include "lm.helloworld.pb.h"

using std::cout;
using std::cerr;
using std::endl;
using std::fstream;
using std::ios;

int main()
{
    lm::helloworld msg1;
    msg1.set_id(1001);
    msg1.set_str("google");

    fstream output("./log", ios::out | ios::trunc | ios::binary);

    if (!msg1.SerializeToOstream(&output)) {
        cerr << "Failed to write msg." << endl;
        return -1;
    }

    return 0;
}

4.编写reader.cc

 /**
  * @file    reader.cc
  * @author  Home Jang(generalibm@gmail.com)
  * @date    2016-06-12 18:08:34
  */

#include "lm.helloworld.pb.h"

#include <iostream>
#include <fstream>

using std::cout;
using std::endl;
using std::fstream;
using std::ios;
using std::cerr;

void listMsg(const lm::helloworld & msg) {
    cout << "id = " << msg.id() << endl;
    cout << "str = " << msg.str() << endl;
}


int main()
{
    lm::helloworld msg1;
#if 1
    {
        fstream input("./log", ios::in | ios::binary);
        if (!msg1.ParseFromIstream(&input)) {
            cerr << "Failed to parse address book." << endl;
            return -1;
        }
    }
#endif  
    listMsg(msg1);

    return 0;
}

5 . 编译执行
./writer
$cat log
$理google

./reader
$ id = 1001
$ str = google

四、 参考资料

[1]https://developers.google.com/protocol-buffers/docs/cpptutorial#defining-your-protocol-format
[2]https://github.com/google/protobuf/blob/master/src/README.md
[3]http://www.ibm.com/developerworks/cn/linux/l-cn-gpb/

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值