什么是protobuf
protobuf全称protocol buffers, 它是google为了序列化结构体而开发的一种跨语言、跨平台、可拓展的一种协议,类似于xml,但更小、更快、更简单。使用protobuf,只要定义了结构体,就可以使用生成的代码,去生成、解析结构体。
工作原理
在protobuf中,我们使用.proto
文件来定义结构体。在.proto
文件中,包含一系列的键值对,来记录数据。如,下面就是一个.proto
文件,用来描述一个人的信息:
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;
}
如上面的代码,每个message类型都有一个或者多个不重复的数据块,每个数据块都由键值对组成,其中的值可以是数字(integer或者float),boolean, strings, raw bytes,或者protobuf协议中其他的message类型(类似于对象,对象中可以包含对象)。数据块可以声明为可选、必选或者可重复的。更多关于.proto
的语法,参考https://developers.google.cn/protocol-buffers/docs/proto。
一旦定义完.proto
文件,就可以使用proto编译器编译出指定语言的源码,包括java, python, c++。生成的代码中,会声明一个Person
类, 通过Person
类,我们可以很方便的序列化、反序列化Person
数据:
Person person;
person.set_name("John Doe");
person.set_id(1234);
person.set_email("jdoe@example.com");
fstream output("myfile", ios::out | ios::binary);
person.SerializeToOstream(&output);
上面的代码,把Person
对象序列化到文件中了,下面我们可以再把Persson
对象解析出来:
fstream input("myfile", ios::in | ios::binary);
Person person;
person.ParseFromIstream(&input);
cout << "Name: " << person.name() << endl;
cout << "E-mail: " << person.email() << endl;
我们可以直接想message中增加新字段,而不用担心兼容性;当解析老二进制数据时,会自动忽略新字段。
为什么不使用xml
和xml相比,protobuf有很多优点:
- 更简单
- 比xml,小3-10倍
- 比xml,快20-100倍
- 更不容易产生歧义
- 使用生成的源码,操作类,对开发者更友好
如下面的例子,如果一个person
有name
和email
属性,我们需要定义xml如下:
<person>
<name>John Doe</name>
<email>jdoe@example.com</email>
</person>
而使用protobuf,如下(protobuf的文本格式)
#注意真正的protobuf数据是二进制数据流
person {
name: "John Doe"
email: "jdoe@example.com"
}
当上面的数据被编码成protobuf二进制数据时,只有28字节;反序列化,解析成对象需要100-200纳秒。而xml数据,需要69字节;反序列化需要5000-10000纳秒。
并且操作protobuf也很简单:
cout << "Name: " << person.name() << endl;
cout << "E-mail: " << person.email() << endl;
如果是xml,我们需要:
cout << "Name: "
<< person.getElementsByTagName("name")->item(0)->innerText()
<< endl;
cout << "E-mail: "
<< person.getElementsByTagName("email")->item(0)->innerText()
<< endl;
当然,protobuf也不都是比xml强。protobuf数据是以二进制数据的方式存储的,人类难以阅读。而xml是自描述的,我们可以直接理解其中的含义;除非我们拿到.proto
文件,否则是很难知道protobuf数据的含义的。
版权声明
本站文章、图片、视频等(除转载外),均采用知识共享署名 4.0 国际许可协议(CC BY-NC-SA 4.0),转载请注明出处、非商业性使用、并且以相同协议共享。
© 空空博客,本文链接:https://www.yeetrack.com/?p=1240
近期评论