Protobuf 开发指南

    欢迎使用protobuf的开发人员文档 - 一种与语言无关,平台无关,可扩展的序列化结构化数据的方法,用于通信协议,数据存储等。

本文档面向希望在其应用程序中使用protobuf的Java,C ++或Python开发人员。本概述介绍了protobuf,并告诉您需要做什么才能开始 - 然后您可以继续学习本 教程 或深入研究 protobuf编码。 还为所有三种语言提供了API 参考文档,以及 用于编写.proto 文件的语言 和 样式指南 。

什么是protobuf?

protobuf是一种灵活,高效,自动化的机制,用于序列化结构化数据 - 想想XML,但更小,更快,更简单。您可以定义数据的结构化时间,然后可以使用特殊生成的源代码轻松地在各种数据流中使用各种语言编写和读取结构化数据。您甚至可以更新数据结构,而不会破坏根据“旧”格式编译的已部署程序。

他们是如何工作的?

您可以通过在.proto 文件中定义protobuf消息类型来指定您希望如何构建序列化信息 。每个protobuf消息都是一个小的逻辑信息记录,包含一系列名称 - 值对。这是一个.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; }

如您所见,消息格式很简单 - 每种消息类型都有一个或多个唯一编号的字段,每个字段都有一个名称和一个值类型,其中值类型可以是数字(整数或浮点数),布尔值,字符串,原始字节,甚至(如上例所示)其他protobuf消息类型,允许您分层次地构建数据。您可以指定可选字段, 必填字段和重复字段。您可以 在Protocol Buffer Language Guide中找到有关编写.proto 文件的 更多信息 。

一旦定义了消息,就可以在.proto 文件上运行应用程序语言的protobuf编译器 来生成数据访问类。这些为每个字段提供了简单的访问器(如 name() 和 set_name()),以及将整个结构序列化/解析为原始字节的方法 - 例如,如果您选择的语言是C ++,则运行编译器上面的例子将生成一个名为Person 的类 。然后,您可以在应用程序中使用此类来填充,序列化和检索 Person protobuf消息。然后你可以写一些这样的代码:

        
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);
然后,稍后,您可以在以下位置阅读您的消息:
        
fstream input("myfile", ios::in | ios::binary); Person person; person.ParseFromIstream(&input); cout << "Name: " << person.name() << endl; cout << "E-mail: " << person.email() << endl;
您可以在消息格式中添加新字段,而不会破坏向后兼容性; 旧的二进制文件在解析时只是忽略新字段。因此,如果您的通信协议使用protobuf作为其数据格式,则可以扩展协议,而无需担心破坏现有代码。

您将在API参考部分找到有关使用生成的protobuf代码的完整参考 ,您可以在protobuf编码中找到有关如何编码protobuf消息的更多信息 。

为什么不使用XML?

对于序列化结构化数据,protobuf比XML具有许多优点。protobuf: 例如,假设您想要为 具有 姓名 和 电子邮件的人建模 。在XML中,您需要:
        
<person> <name>John Doe</name> <email>jdoe@example.com</email> </person>
而相应的protobuf 协议格式是:
        
# Textual representation of a protocol buffer. # This is *not* the binary format used on the wire. person { name: "John Doe" email: "jdoe@example.com" }

当此消息被编码为protobuf 二进制格式 (上面的文本格式只是用于调试和编辑的方便的人类可读表示)时,它可能长达28个字节并且需要大约100-200纳秒来解析。如果删除空格,XML版本至少为69个字节,并且需要大约5,000-10,000纳秒才能解析。

此外,操作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不是使用标记(例如HTML)对基于文本的文档建模的好方法,因为您无法轻松地将结构与文本交错。此外,XML是人类可读的和人类可编辑的; protobuf,至少是它们的原生格式,不是。XML在某种程度上也是自我描述的。只有拥有消息定义(.proto 文件)时,protobuf才有意义 。


粤ICP备16014574号