简介
Protocol buffers是一种灵活有效的将数据序列化的工具,类似于XML,但它存储使用更少,更快速,使用更简单。仅仅需要定义一些自己需要的结构化数据,利用protobuf可以生成一些特殊的代码,利用这些代码我们可以利用不同的语言读写这些数据。
OK,说了这么多那么它到底是如何工作的呢?
通过在protocol buffer 的文件 .proto中定义一些message(类似C++的class和struct),用户可以自定义数据的序列化形式。
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 type = 2 [default = HOME];
}
repeated PhoneNumber phone = 4;
}
每一个Protocol buffer 都可以利用类似的代码描述期望的结构。它包含了很多name-value对。从上述代码可以看出其语法十分简单。每一个message都包含了一个或者多个有唯一标示的域(fileds)。每一个域都有一个name和value。value可以是多种类型的,如:整型,浮点型,布尔型,string,或者是用bytes表示,也可以用其他message嵌套。
Protocol buffer总共有3类域:optional,required,repeated。我们可以在Protocol Buffer Language Guide找到更多的信息,之后我也会详细介绍。
一旦定义了自己的message,我们就可以利用protocol编译 .proto文档,生成一些类文件。这些类提供了一些接入数据的方法,如一些比较常规的get和set方法,以及一些序列化(serialize)和解析(parse)的方法。例如,我们这里用C++做展示,上述例子利用protocol buffer生成一个叫做Person的类。
在应用中添加这个类,通过如下方法可以对类里面的成员进行赋值,检索,序列化等操作。
Person person;
person.set_name("Mallock");
person.set_id(1234);
person.set_email("Mallock@example.com");
fstream output("myfile", ios::out | ios::binary);
person.SerializeToOstream(&output);
最后一个方法是序列化,将数据序列化之后,我们可以通过protocol buffer提供的方法解析和检索。
fstream input("myfile", ios::in | ios::binary);
Person person;
person.ParseFromIstream(&input);
cout << "Name: " << person.name() << endl;
cout << "E-mail: " << person.email() << endl;
当然我们也可以在不破坏向后兼容的条件下,增加一些新的域(必然有一些限制)。旧的解析方法仍旧可以解析旧的域,并且会忽略新的域。所以我们可以在不修改原来代码的情况下扩展protocol buffer。
很简单吧!简单来说protocol buffer干了以下的事情:
- 提供结构化方法
- 提供设置和检索数据方法
- 提供列化可解析方法
- 提供扩展方法并向后兼容