Protobuf(Protocol Buffers),是 Google 开发的一种跨语言、跨平台的可扩展机制,用于序列化结构化数据。java
与 XML 和 JSON 格式相比,protobuf 更小、更快、更便捷。protobuf 目前支持 C++、Java、Python、Objective-C,若是使用 proto3,还支持 C#、Ruby、Go、PHP、JavaScript 等语言。python
官网地址:developers.google.cn/protocol-bu…git
GitHub 地址:github.com/protocolbuf…github
优势:bash
缺点:性能
下载地址:github.com/protocolbuf…ui
下载 protoc-3.9.1-win64.zip,这个是编译后的压缩包,至关于绿色版,解压后,将其下的 bin 目录添加到环境变量就能够了,省去了安装的麻烦。google
而后打开命令提示符,输入命令:编码
protoc --version
复制代码
成功显示版本号,则表示安装成功。以下图:spa
使用 protobuf 首先须要定义 .proto 文件,先来看一个简单的例子。
定义 Person.proto 文件,内容以下:
syntax = "proto3";
package Test;
message Person {
string Name = 1;
int32 Age = 2;
bool Marriage = 3;
}
复制代码
syntax = "proto3";
指定正在使用 proto3 语法,不然 protobuf 将默认使用的是 proto2。package Test;
指定命名空间(C# 中)。message
是关键字,定义结构化数据。protoc 是 protobuf 自带的编译器,能够将 .proto 文件编译成 java、python、go、C# 等多种语言的代码,直接引用。
编译命令:
protoc -I=E:\GL\Test2017 --python_out=E:\GL\Test2017 Person.proto
复制代码
编译命令说明:
安装 protobuf
。
调用编译命令编译 Person.proto,编译后生成文件:Person_pb2.py
,添加至项目中,序列化和反序列化示例以下:
import Person_pb2
person = Person_pb2.Person()
person.Name = '张三'
person.Age = 20
person.Marriage = True
# 序列化
b = person.SerializeToString()
print(b)
# 反序列化
p = Person_pb2.Person()
p.ParseFromString(b)
print(f'Name: {p.Name}; Age: {p.Age}; Marriage: {p.Marriage}')
复制代码
输出:
b'\n\x06\xe5\xbc\xa0\xe4\xb8\x89\x10\x14\x18\x01'
Name: 张三; Age: 20; Marriage: True
复制代码
注意,不能这样写,这是错误的:
p = Person_pb2.Person().ParseFromString(b)
复制代码
C# 下的 Protobuf 有 3 个版本:
这里咱们介绍谷歌官方版本。
在 VS 中,经过 NuGet 安装 'google.protobuf' 包。
using Google.Protobuf;
using System;
using Test;
namespace Protobuf
{
class Program
{
static void Main(string[] args)
{
Person person = new Person();
person.Name = "张三";
person.Age = 20;
person.Marriage = true;
// 序列化
byte[] buffer = person.ToByteArray();
foreach (byte b in buffer)
{
Console.Write(b.ToString("X2") + " ");
}
Console.WriteLine();
// 反序列化
Person p = Person.Parser.ParseFrom(buffer);
Console.WriteLine(string.Format("Name: {0}, Age: {1}, Marriage: {2}", p.Name, p.Age, p.Marriage));
Console.Read();
}
}
}
复制代码
输出:
0A 06 E5 BC A0 E4 B8 89 10 14 18 01
Name: 张三, Age: 20, Marriage: True
复制代码
比较一下 Python 的输出,好像不同,Python 中第一个字节是 \n,而这里是 0A。\n 在 ASCII 中的值就是 0A。因此两种语言的序列化结果是同样的。