目录
1.介绍
1.1官方解释
1.2 通俗解释
1.3 为什么要用protobuf
2. 安装
3. Proto文件编译
4. 使用编译后的文件
5. 将类文件信息转化为字节流
5.1 通过流的形式转化
5.2 直接通过函数转化
附: Sublime3 配置proto文件语法高亮
1.介绍
1.1官方解释
Protobuf应该是Protoc buffers(协议缓冲区),官方解释直接翻译官网的介绍,概括一下就是:Protocol buffers are a flexible, efficient, automated mechanism for serializing structured data – think XML, but smaller, faster, and simpler. You define how you want your data to be structured once, then you can use special generated source code to easily write and read your structured data to and from a variety of data streams and using a variety of languages. You can even update your data structure without breaking deployed programs that are compiled against the "old" format.
翻译一下就是:协议缓冲区是一种灵活,高效,自动化的机制,用于序列化结构化数据 - 想想XML,但更小,更快,更简单。 您可以定义数据的结构化结构,然后使用特殊生成的源代码轻松地将结构化数据写入和读取各种数据流,并使用各种语言。 您甚至可以更新数据结构,而不会破坏根据“旧”格式编译的已部署程序。
1.2 通俗解释
protobuf是一种与平台无关,语言无关、可扩展且轻便高效序列化数据结构的协议,可用于网络通讯和数据存储。想象你有一个Person类,类里面有很多成员属性,然后你想把一个Person对象发送到另外一台机器上,一般而言,你是不能直接将这个对象是发送过去的,你需要将这个类序列化,以字节流的形式发送,那么你如何将你的对象序列化,就是一个问题,而且你还要考虑到接收端将数据反序列化。Protobuf就是来做这个事情的,它本身与具体语言无关,支持绝大多数主流编程语言,如C++,java,python,C#等。或者,你可以理解为加密文件,你要发的汉子通过加密后编程了一堆不同排列的小圆点,只要你的朋友有这个加密文件,他就能将你加密的东西翻译过来。
1.3 为什么要用protobuf
一图以蔽之。
关于性能,网上有一些测评,这里给一个测评链接:https://blog.csdn.net/xiaoxiaoyusheng2012/article/details/81102369
2. 安装
protobuf的安装教程官网上有,但是这个安装也还不是特别容易。不过已经有很多博客介绍了在linux上的安装教程,在windows上安装反而没那么好安装,毕竟命令行还是在linux下用的舒服些。所以这里只介绍在windows上安装Protobuf的方法。
本文提供一种简单的安装方法,首先你需要下载visual studio ,我这里的版本是visual studio 2017 community。其他版本没有测试,但是估计只要不是太老旧的版本都应该可以。
首先用vs建立一个工程。我这里建立的是一个C#的控制台应用程序。如下:
点击确定:
点击:工具->NuGet包管理器->管理方案的Nuget解决包。
搜索protobuf:
选中项目,点击安装,安装完成后,会在下方提示:安装完成。
同样的方式搜索protobuf.tools, 选中项目点击安装。
安装完成之后,到nuget文件夹下查看,是否有这两个文件夹,有的话,说明安装成功了。
如果你下次新建一个工程时,可能会发现在Guget解决方案的已安装目录下并没有发现这两个文件夹。但是在packages中确实也存在这个。所以我们肯定不用再次安装,事实确实如此,我们只需要添加一个引用即可。
选择项目中的:引用->右键添加->浏览,选择Google.Protobuf.dll .即可。
那么在VS中配置protobuf就算完成了。需要说明的是,我们在VS中下载的两个protobuf文件,第一个是用于程序运行时的动态链接库,第二个是用于编译proto文件的工具。
3. Proto文件编译
关于proto文件的编写,建议有条件的翻墙去谷歌官网上看详细教程,要是不能上网,也可以参考一些国内的博客,如《Protobuf语言指南——.proto文件语法详解》。
根据官网的C#使用protobuf的教程,我直接先建了一个叫Person.proto的文件,具体内容如下:
syntax="proto3";
package tutorial;import "timestamp.proto";message Person
{string name=1;int32 id=2;string email=3;enum PhoneType{HOME=0;WORK=1;MOBILE=2;}message PhoneNumber{string number=1;PhoneType type=2;}repeated PhoneNumber phones=4;google.protobuf.Timestamp last_update=5;
}
值得说明的是,timestamp.proto是谷歌自己定义好的文件,用于存放时间戳的,在编译proto文件时需要将timestamp.proto放在和Person.proto同一目录下,如果不是同一路径,则需要指定绝对路径。为了方便,我将这两个文件都放在了google.protobuf.tools/3.6.1/tools下:
编写好proto文件后就可以开始编译了,proto文件的编译有一套固定的指令,在当前文件夹下打开命令行窗口,输入:
C:\Users\Paul\.nuget\packages\google.protobuf.tools\3.6.1\tools\windows_x64>protoc -I=. --csharp_out=. Person.proto
如果你要编译为java类,那就将csharp_out替换为java_out,C++替换为cpp_out. 运行成功后会出现Person.cs
文件,这个文件就是我们需要的类文件,即我们认为的序列化Person类的密码。至此编译工作就结束了。
4. 使用编译后的文件
有了编译后的类文件,我们就可以将该文件复制到我们的工程目录下。复制后在解决方案中可能不能直接显示出来,右键工程名选择添加现有项,选择刚才的Person.cs即可。
由于我们没有指定命名空间,所以Person类默认会以Package的名字作为命名空间。在主程序Program.cs中加入:
using Tutorial;
using Google.Protobuf;
就可以使用Person类了,我们在主函数中添加代码,首先构造一个Person对象。然后将其写入二进制文件,然后再将其解析出来。我的工程结构如下:
主函数代码如下:
using Tutorial;
using static System.Console;
using Google.Protobuf;
using System.IO;namespace ProtobufTest
{class Program{static void Main(string[] args){Person john = new Person{Id = 1234,Name = "John Doe",Eamail = "956441598@qq.com",Phones = { new Person.Types.PhoneNumber { Number = "0707007", Type = Person.Types.PhoneType.Home } }};//serializztionusing (var output = File.Create("john.dat")){john.WriteTo(output);}//parsing Person john2;using (var input = File.OpenRead("john.dat")){john2 = Person.Parser.ParseFrom(input);}WriteLine("Name:{0},\n\t Id:{1},\n\t Email:{2}",john2.Name,john2.Id,john2.Eamail);WriteLine(" \t the {0} phone is :{1}", john2.Phones[0].Type, john2.Phones[0].Number);}}
}
运行这段代码会在工程的dubug文件夹下多出一个john.dat文件。这就是本地序列化后的文件。
5. 将类文件信息转化为字节流
5.1 通过流的形式转化
byte[] bytes;using (MemoryStream stream = new MemoryStream()){//save the person to streamjohn.WriteTo(stream);bytes = stream.ToArray();}Person john_copy = Person.Parser.ParseFrom(bytes);
5.2 直接通过函数转化
bytes = john.ToByteArray();
Person john_copy2 = Person.Parser.ParseFrom(bytes);
Google.Protobuf 参考链接:github
附: Sublime3 配置proto文件语法高亮
Sublime本身不支持proto文件语法高亮,但是早有人想到了这一点,所以网上有如何配置proto语法高亮的教程,这里推荐一个链接吧:教程。亲测可用。