一.简介
google protobuf是一个灵活的、高效的用于序列化数据的协议。相比较XML和JSON格式,protobuf更小、更快、更便捷。google protobuf是跨语言的,并且自带了一个编译器(protoc),只需要用它进行编译,可以编译成Java、python、C++、C#、Go等代码,然后就可以直接使用,不需要再写其他代码,自带有解析的代码。
更详细的介绍见:
https://developers.google.com/protocol-buffers/
二.与其他技术比较
世上还有很多其他的类似技术啊,比如 XML,JSON,Thrift 等等。和他们相比,Protobuf 有什么不同呢?
优点:简单说来 Protobuf 的主要优点就是:简单,快。
缺点:Protbuf 与 XML 相比也有不足之处。它功能简单,无法用来表示复杂的概念。XML 已经成为多种行业标准的编写工具,Protobuf 只是 Google 公司内部使用的工具,在通用性上还差很多。
三.proto文件
.proto文件是protobuf一个重要的文件,它定义了需要序列化数据的结构。使用protobuf的3个步骤是:
1 在.proto文件中定义消息格式
2 用protobuf编译器编译.proto文件
3 用C++/Java等对应的protobuf API来写或者读消息
四.一个简单的例子
该程序示例的大致功能是,定义一个Person结构体和存放Person的AddressBook,然后一个写程序向一个文件写入该结构体信息,另一个程序从文件中读出该信息并打印到输出中。
- addressbook.proto文件
package zhb;
message Person {
required string name = 1;
required int32 age = 2;
}
message AddressBook {
repeated Person person = 1;
}
- wirte.cpp
#include <iostream>
#include <fstream>
#include <string>
#include "addressbook.pb.h"
using namespace std;
void PromptForAddress(zhb::Person *person) {
cout << "Enter Person name & age:" << endl;
string name;
cin >> name;
person->set_name(name);
int age;
cin >> age;
person->set_age(age);
}
int main(int argc, char **argv) {
if (argc != 2) {
cerr << "Usage: " << argv[0] << " ADDRESS_BOOL_FILE" << endl;
return -1;
}
zhb::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 << "Filed to parse address book." << endl;
return -1;
}
}
// Add an address
PromptForAddress(address_book.add_person());
{
fstream output(argv[1], ios::out | ios::trunc | ios::binary);
if (!address_book.SerializeToOstream(&output)) {
cerr << "Failed to write address book." << endl;
return -1;
}
}
return 0;
}
3.read.cpp
#include <iostream>
#include <fstream>
#include <string>
#include "addressbook.pb.h"
using namespace std;
void ListPeople(zhb::AddressBook* address_book) {
for (int i = 0; i < address_book->person_size(); i++) {
const zhb::Person& person = address_book->person(i);
zhb::School* school = address_book->mutable_school();
cout << "school id:" << school->id() <<endl;
cout << person.name() << " " << person.age() <<
"school:" << school->name() << endl;
school->set_id(999);
school->set_name("my_school");
}
}
int main(int argc, char **argv) {
if (argc != 2) {
cerr << "Usage: " << argv[0] << " ADDRESS_BOOL_FILE" << endl;
return -1;
}
zhb::AddressBook address_book;
{
fstream input(argv[1], ios::in | ios::binary);
if (!address_book.ParseFromIstream(&input)) {
cerr << "Filed to parse address book." << endl;
return -1;
}
input.close();
}
ListPeople(&address_book);
ListPeople(&address_book);
return 0;
}
4.BUILD文件
cc_binary(
name = 'write',
srcs = 'write.cpp',
deps = [
':address_proto',
]
)
cc_binary(
name = 'read',
srcs = 'read.cpp',
deps = [
':address_proto',
]
)
proto_library(
name = 'address_proto',
srcs = 'addressbook.proto',
)
5.编译运行
blade build
运行结果: