maltadirk 发表于 2022-11-2 07:11

七爪源码:学习用于序列化结构化数据的协议缓冲区 (Protobuf ...

在讨论 Protocol Buffers 之前,让我们先了解一下序列化和反序列化。
序列化 — 将对象转换为线性字节序列以便存储或传输到另一个位置的过程。 这种序列化对象的过程也称为编组对象。
反序列化 - 获取存储信息并从中重新创建对象的过程。 从一系列字节中提取数据结构称为解组。
随着数据的发展,序列化和反序列化数据的方法也在发展。 让我们谈谈其中的几个。

逗号分隔值 (CSV)
CSV 易于解析和读取,但存在一些缺点,例如必须推断数据类型,并且不能保证。 当数据包含逗号并且列名可能存在也可能不存在时,解析变得很棘手。



关系表定义
关系表定义添加类型,如
CREATE TABLE authors {
             title varchar(255),
             author varchar(80),
             isbn13 varchar(20),
             page int
}优点是数据是完全类型化的,并且可以放入表格中。 但是数据必须是平面的,数据存储在数据库中,不同的数据库其数据定义会有所不同。

JavaScript 对象表示法 (JSON)
JSON 数据可以采用任何形式,并且是网络上广泛接受的格式。 JSON 可以被大多数编程语言读取,并且可以通过网络轻松共享。 但是 JSON 数据没有模式强制,而且 JSON 对象的大小非常大,因为重复的键。
{"title":"Clean Code","author":"Robert C Martin","isbn13":"978-8131773383","pages":434}在 JSON 对象中,像 {}[],: 这样的字符不具有任何类型的数据,它只是帮助序列化程序格式化数据,以便对其进行解码和结构化。
JSON对象长度:87字节
实际数据长度:42字节
非数据长度:45 字节,这是数据传输过程中的总浪费。

可扩展标记语言 (XML)
XML 也使用类似于 JSON 的元标记,但它们也有结束标记。 由于它们具有结束标记,因此与 JSON 相比,它们的大小要大得多。
<?xml version="1.0" encoding="UTF-8" ?><root><title>Clean Code</title><author>Robert C Martin</author><isbn13>978-8131773383</isbn13><pages>434</pages></root>XML 文档长度:158 字节
实际数据长度:42字节
非数据长度:116 字节,这是数据传输过程中的总浪费。

协议缓冲区
Protocol Buffers 或 Protobuf 是一种数据序列化协议,如 JSON 或 XML。但与它们不同的是,Protobuf 不适合人类使用,序列化数据是编译后的字节,难以供人类阅读。
Protocol Buffers 是 Google 用于序列化结构化数据的语言中立、平台中立的可扩展机制。

优点

[*]数据是完全类型
[*]数据自动压缩,这意味着更少的 CPU 使用率
[*]生成代码和读取数据需要模式(.proto 文件)
[*]文档可以嵌入到模式中
[*]可以跨多种语言读取数据(C++、C#、Dart、Go、Java、Objective-C、JavaScript、Ruby、PHP、Kotlin 和 Python)
[*]Schema 可以随着时间的推移而发展,并支持向后兼容
[*]与 JSON 和 XML 相比,它更小更快
[*]可以使用代码生成器自动生成代码

缺点

[*]因为是压缩序列化的,无法在文本编辑器中打开
[*]支持有限的编程语言
Protobuf 由 .proto 文本文件定义,人类可以轻松阅读和理解。
在 Protobuf 中一切都是消息,消息相当于编程语言中的类或结构。
syntax="proto3" 告诉编译器我们正在使用第 3 版的 Protocol Buffers。在消息体中,我们可以定义与消息关联的字段。它支持无符号整数、有符号整数、浮点数、双精度数、字节数组、字符串、布尔值、枚举和用户定义的消息。
因此,让我们看看我们为上述 JSON 示例有效负载获得了哪些序列化数据。我已将序列化数据分解为多行,以显示每行之后的编码情况。
序列化数据长度:48字节
实际数据长度:42字节
非数据长度:仅在数据传输过程中总共浪费了 6 个字节。

跨编程语言共享数据
当我们在 .proto 文件上运行 Protocol Buffers 编译器时,编译器会以所选语言生成代码。我们只需要使用我们在 .proto 文件中描述的消息类型,包括获取、设置字段值、将消息序列化到输出流以及从输入流解析消息。


协议缓冲区样式指南
Google 提供了设计 .proto 文件的样式指南,我们应该尽量遵守它们。

标准文件格式

[*]保持行长为 80 个字符
[*]使用 2 个空格的缩进
[*]更喜欢对字符串使用双引号

文件结构

[*]文件应命名为 lower_snake_case.proto
[*]所有文件应按以下方式排序:
1. 许可证标题(如果适用)
2.文件概述
3. 语法
4. 包装
5. 进口(排序)
6.文件选项
7. 其他一切

套餐
包名应该是小写的。 包名称应具有基于项目名称的唯一名称。

消息和字段名称
使用 CamelCase(首字母大写)作为消息名称
使用 underscore_separated_names 作为字段名
如果您的字段名称包含数字,则该数字应出现在字母之后,而不是像 media_artist1 这样的下划线之后
message MediaServerRequest {
optional string media_name = 1;
optional string media_artist1 = 2;
}
重复字段

[*]对重复字段使用复数名称
message MediaServerRequest {
repeated string songs = 1;
}
枚举

[*]枚举类型名称使用 CamelCase(首字母大写),值名称使用 CAPITALS_WITH_UNDERSCORES
enum RequestStatus {
REQUEST_STATUS_DEFAULT = 0;
REQUEST_STATUS_FIRST_VALUE = 1;
REQUEST_STATUS_SECOND_VALUE = 2;
}
定义消息类型
让我们分解我们的 author.proto 消息类型以查看它的所有组件。



定标器字段类型

[*]数字 - 数字可以采用各种形式,具体取决于您希望它们具有的值 double(64bits)、float(32 bits)、int32、uint32、sint32、sint64、fixed64、sfixed32、sfixed64
Boolean — Boolean 可以保存值 True 或 False。它在 Protobuf 中表示为 bool
String — String 表示任意长度的文本。它在 Protobuf 中表示为字符串。字符串必须始终包含 UTF-8 编码或 7 位但 ASCII 文本
字节 - 字节代表字节数组的任何序列。它在 Protobuf 中表示为字节

字段标签
在 Protocol Buffers 中,字段名称并不重要,它们仅在编程中引用字段时才重要。对于 Protobuf,字段标签很重要,最小标签值可以是 1,最大标签值可以是 2–1 或 536,870,911。我们也不能使用数字 19000 到 19999。编号从 1 到 15 的标签仅使用 1 个字节,而编号从 14 到 2047 的标签使用 2 个字节。因此,对经常填充的字段使用 1 到 15 个标签号。

重复字段
要制作列表或数组,我们可以使用重复字段的概念。该列表可以包含我们想要的任意数量的元素,甚至是 0。

注释
要向 .proto 文件添加注释,请使用 C/C++ 样式 // 和 /* */ 语法。

枚举
如果我们事先知道一个字段可以取的所有值,我们就可以利用枚举类型。枚举必须以标记 0 开头,这也是默认值。

默认字段值
如果未指定任何值,所有字段都将采用默认值。
bool - 假
number - 0
string - 空字符串
bytes - 空字节
重复 - 空列表
enum - 第一个值

使用其他消息类型
我们可以使用其他消息类型作为字段类型,也可以在同一个 .proto 文件中定义。

嵌套类型
可以在类型中定义类型,这有助于避免命名冲突并加强该类型的某种程度的局部性。 如果您想在其父消息类型之外重用此消息类型,我们可以将其称为_Parent_._Type_。 我们可以随意嵌套消息。
在下一篇文章中,我们将讨论 Protocol Buffers 的高级概念。
关注七爪网,获取更多APP/小程序/网站源码资源!
页: [1]
查看完整版本: 七爪源码:学习用于序列化结构化数据的协议缓冲区 (Protobuf ...