翻译自:https://developers.google.com/protocol-buffers/docs/overview
Protocol buffers是什么?
Protocol buffers是一款灵活、高效、自动化的数据描述语言。类似于XML能够将结构化数据序列化,但比XML更小,更快,更简单。通过它,你可以定义你的数据的结构,并生成基于各种语言的代码。这些你定义的数据流可以轻松地再传递并不破坏你已有的程序。并且你也可以更新这些数据而现有的程序也不会受到任何的影响。
Protocol buffers是怎样工作的?
通过定义一些数据和结构放在一个 .proto 文件之中。每一个protocol buffer 消息都是一小段结构,包含了一些名字。下面是一个.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;
- }
就像你看到的,这个消息的格式是十分简单的——对于每个消息类型都有一个或多个独特的数字字段,每一个字段都有一个名称和类型,可以是数字(整型或浮点),布尔,字符,原始字节,又或者是其它的protocol buffer消息类型,例如你自定义分层的数据结构。你还可以定义可选的required和repeated字段。你可以在这里Protocol Buffer Language Guide.找到更多编写.proto文件的信息。
在定义好了.proto文件,就可以将该文件作为protocol buffers编译器的输入文件,编译产生特定语言的数据定义代码文件了。编译器提供了简单的访问方法为每个字段(如name()和set_name())序列化/解析整个结构到原始字节——那么,举个栗子,如果你用的是C++,用这个编译器运行上面的例子会产生一个叫Person的类。你可以在你的应用中运用这个Person protocol buffer消息。你或许需要写一些像这些的代码:
- Person person;
- person.set_name( "John Doe");
- person.set_id( 1234);
- person.set_email( "[email protected]");
- 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;
你可以增加一些新字段到你的消息格式中,这样并不会影响向后兼容;旧的二进制文件解析时会简单地忽略新的字段。所以如果你有通讯的协议是用到protocol buffers当作数据格式的话,你不用担心扩展你的协议会影响到原有的代码。
你可以在这里API Reference section找到关于使用生成protocol buffer的完整事例,你也可以在这里Protocol Buffer Encoding找到更多内容关于protocol buffer消息是怎样编码的。
为什么不使用XML?
同XML相比,Protocol buffers在序列化结构化数据方面有许多优点:
1. 更简单
2. 数据描述文件只需原来的1/10至1/3
3. 解析速度是原来的20倍至100倍
4. 减少了二义性
5. 生成了更容易在编程中使用的数据访问类
举个栗子,如果你想写一个带有name和email的person。在XML里,你需要这样写:
- <person>
- <name>John Doe</name>
- <email>[email protected]</email>
- </person>
而相应的protocol buffer消息(应用protocol buffer文本格式)是:
- # Textual representation of a protocol buffer.
- # This is *not* the binary format used on the wire.
- person {
- name: "John Doe"
- email: " [email protected]"
- }
当编码这段消息到protocol buffer二进制格式时(注释只是用来帮助人们调试和修改),它可能只有28字节和大约花费100到200纳秒的解释时间。但是如果用XML,它至少有69字节(如果你去掉空格)和花费5000到10000纳秒的解释时间。
而且,操作protocol buffer更加容易:
- 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;
然而,protocol buffers不总是比XML好——例如,protocol buffers不是一个写基于文本的文档标记(例如HTML)的好方法,你不能轻易地交互结构和文本。还有,XML比较好看还好写,但protocol buffers,即使在原始格式下,也不是很好看,很好写。XML在某种程度上可以自描述。protocol buffer只在你有消息定义文件(.proto文件)时才有意义。
听起来好像挺适合我的!我要怎样开始?
先在这里Download the package下个包——这个包已经包含了各种语言(其实就只有Java,Pythin和C++)的protocol buffer编译器完整代码,当然,你还需要I/O和testing这些类。生成和安装你的编译器前,请看看README里的说明。
当你搞定一切的时候,你可以看看你所选择的语言的tutorial——这会帮你建立一个简单的用到protocol buffers的应用。
proto3介绍
我们最近做了一个新版本——Protocol Buffers language version 3(又叫做proto3),你可以在这里下载alpha release,我们加了一些新特性。我们简化了这个语言,现在可以用在更多的语言上了(C++,Python,JavaNano,Ruby,Objective-C和C#,不过有一些限制some limitations)。你还可以用在Go上,通过最新的Go protoc插件golang/protobuf。我们还在计划在更多的语言上用到protocol buffers。
还有一些内容和历史的问题就不翻译了。