目录

  1. 什么是protobuffer?
  2. protobuffer是如何工作的?
  3. 为什么不用xml?

1.什么是protobuffer?

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

2.protobuffer是如何工作的?

您可以通过在.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;
}

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

一旦定义了消息,就可以在.proto文件上运行应用程序语言的协议缓冲区编译器来生成数据访问类。这些为每个字段(如name()set_name())提供了简单的访问器,以及将整个结构序列化/解析为原始字节的方法 - 例如,如果您选择的语言是C ++,则在上面的示例中运行编译器将生成了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);

然后可以这样读入消息

 fstream input("myfile", ios::in | ios::binary);
Person person;
person.ParseFromIstream(&input);
cout << "Name: " << person.name() << endl;
cout << "E-mail: " << person.email() << endl;

您可以在消息格式中添加新字段,而不会破坏向后兼容性; 旧的二进制文件在解析时只是忽略新字段。因此,如果您的通信协议使用协议缓冲区作为其数据格式,则可以扩展协议,而无需担心破坏现有代码。

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

3.为什么不使用XML?

对于序列化结构化数据,protobuffer比XML具有许多优点。protobuffer:

  • 更简单
  • 比小3到10倍
  • 快20到100倍
  • 不那么暧昧
  • 生成更易于以编程方式使用的数据访问类

例如,假设你想要定义一个拥有一个name和email的person。在XML中,您需要:

 <person>
<name>John Doe</name>
<email>jdoe@example.com</email>
</person>

而使用相应的protobuffer是:

 # Textual representation of a protocol buffer.
# This is *not* the binary format used on the wire.
person {
name: "John Doe"
email: "jdoe@example.com"
}

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

此外操作protobuffer数据更容易:

 cout << "Name: " << person.name() << endl;
cout << "E-mail: " << person.email() << endl;

如果你是用xml,可能是这个样子:

  cout << "Name: "
<< person.getElementsByTagName("name")->item()->innerText()
<< endl;
cout << "E-mail: "
<< person.getElementsByTagName("email")->item()->innerText()
<< endl;

但是,protobuffer并不总是比XML更好的解决方案 - 例如,protobuffer不是使用标记(例如HTML)对基于文本的文档建模的好方法,因为您无法轻松地将结构与文本交错。此外,XML是人类可读的和人类可编辑的; XML在某种程度上也是自我描述的。只有拥有消息定义(.proto文件)时,protobuffer才有意义。

Protobuffer教程的更多相关文章

  1. Angular2入门系列教程7-HTTP(一)-使用Angular2自带的http进行网络请求

    上一篇:Angular2入门系列教程6-路由(二)-使用多层级路由并在在路由中传递复杂参数 感觉这篇不是很好写,因为涉及到网络请求,如果采用真实的网络请求,这个例子大家拿到手估计还要自己写一个web ...

  2. Angular2入门系列教程6-路由(二)-使用多层级路由并在在路由中传递复杂参数

    上一篇:Angular2入门系列教程5-路由(一)-使用简单的路由并在在路由中传递参数 之前介绍了简单的路由以及传参,这篇文章我们将要学习复杂一些的路由以及传递其他附加参数.一个好的路由系统可以使我们 ...

  3. Angular2入门系列教程5-路由(一)-使用简单的路由并在在路由中传递参数

    上一篇:Angular2入门系列教程-服务 上一篇文章我们将Angular2的数据服务分离出来,学习了Angular2的依赖注入,这篇文章我们将要学习Angualr2的路由 为了编写样式方便,我们这篇 ...

  4. Angular2入门系列教程4-服务

    上一篇文章 Angular2入门系列教程-多个组件,主从关系 在编程中,我们通常会将数据提供单独分离出来,以免在编写程序的过程中反复复制粘贴数据请求的代码 Angular2中提供了依赖注入的概念,使得 ...

  5. Angular2入门系列教程1-使用Angular-cli搭建Angular2开发环境

    一直在学Angular2,百忙之中抽点时间来写个简单的教程. 2016年是前端飞速发展的一年,前端越来越形成了(web component)组件化的编程模式:以前Jquery通吃一切的田园时代一去不复 ...

  6. wepack+sass+vue 入门教程(三)

    十一.安装sass文件转换为css需要的相关依赖包 npm install --save-dev sass-loader style-loader css-loader loader的作用是辅助web ...

  7. wepack+sass+vue 入门教程(二)

    六.新建webpack配置文件 webpack.config.js 文件整体框架内容如下,后续会详细说明每个配置项的配置 webpack.config.js直接放在项目demo目录下 module.e ...

  8. wepack+sass+vue 入门教程(一)

    一.安装node.js node.js是基础,必须先安装.而且最新版的node.js,已经集成了npm. 下载地址 node安装,一路按默认即可. 二.全局安装webpack npm install ...

  9. Virtual Box配置CentOS7网络(图文教程)

    之前很多次安装CentOS7虚拟机,每次配置网络在网上找教程,今天总结一下,全图文配置,方便以后查看. Virtual Box可选的网络接入方式包括: NAT 网络地址转换模式(NAT,Network ...

随机推荐

  1. .net代码混淆 .NET Reactor 研究 脚本一键混淆一键发布

    .net代码混淆 .NET Reactor 研究 为什么要混淆? .net比较适合快速开发桌面型应用,但缺点是发布出来的文件是可以反编译的,有时候为了客户的安全,我们的代码或者我们的逻辑不想让别人知道 ...

  2. springboot 多线程的使用

    int pageSize = 10000; int totalCount = doctorDAO.selectDatasByMapCount2(jsonArray, false, null); int ...

  3. Pycharm从虚拟环境切换到本地环境

    切换到本地: 点击左上角File – settings , 在打开的对话框中选择:Project xxx (xxx是你项目的名称) – Project Interpreter ,在右边可以看到解释器, ...

  4. 【HANA系列】SAP HANA中null变成问号的问题

    公众号:SAP Technical 本文作者:matinal 原文出处:http://www.cnblogs.com/SAPmatinal/ 原文链接:[HANA系列]SAP HANA中null变成问 ...

  5. API接口设计的五大公共参数

    1.平台参数 2.操作系统参数 iOS.Android.PC等等 3.软件版本参数 4.udid号(设备唯一ID) 每个设备都会有一个唯一udid 5.渠道号 app软件从那个渠道下载

  6. java位运算定义常量

    简单说一下位运算 按位与(&) 参加运算的两个数,换算为二进制(0.1)后,进行与运算.只有当相应位上的数都是1时,该位才取1,否则该为为0 按位或(|) 参加运算的两个数,换算为二进制(0. ...

  7. python利用smtp发送邮件

    #!/usr/bin/env python # -*- encoding: utf-8 -*- # author:IversOn5 import requests import json import ...

  8. Tensorflow实战第十一课(RNN Regression 回归例子 )

    本节我们会使用RNN来进行回归训练(Regression),会继续使用自己创建的sin曲线预测一条cos曲线. 首先我们需要先确定RNN的各种参数: import tensorflow as tf i ...

  9. Installation failed with message Failed to commit install session 634765663 with command cmd package

    用小米真机测试时,安装app总会提示这个错误两遍,然后再重新安装. 解决办法:去掉这个√.

  10. Spring基于SchedulingConfigurer实现定时任务

    Spring 基于 SchedulingConfigurer 实现定时任务,代码如下: import org.springframework.scheduling.annotation.Schedul ...