C# protobuf的使用方法 html
protocolbuffer(如下简称PB)是google 的一种数据交换的格式,它独立于语言,独立于平台。
google 提供了多种语言的实现:java、c#、c++、go 和 python,每一种实现都包含了相应语言的编译器以及库文件。
因为它是一种二进制的格式,比使用xml 进行数据交换快许多。能够把它用于分布式应用之间的数据通讯或者异构环境下的数据交换。
做为一种效率和兼容性都很优秀的二进制数据传输格式,能够用于诸如网络传输、配置文件、数据存储等诸多领域。
github上相关开源项目代码:http://pan.baidu.com/s/1eSDSb5ojava
下面演示如何将protobuf的消息体导出成C#支持的.cs类python
首先咱们获取到以下.proto文件c++
package hrv; option java_package = "com.******.****.***.protobuf"; option java_outer_classname = "RequestProto"; message Request { extensions 100 to max; enum Type { LOGIN = 0; CHANGE_PASSWORD = 1; START_SCALE = 2; STOP_SCALE = 3; DATA_PPG = 4; DATA_EP = 5; DATA_HRV = 6; DATA_IBI = 7; MARK_SCALE = 8; RESOURCE_LIST = 9; UPDATE_USER_INFO = 10; GET_SCALE_LIST = 11; GET_SCALE = 12; } required Type type = 1; optional string timestamp = 2; }
而后下载导出工具 ProtoGen.exe 下载地址: http://pan.baidu.com/s/1eRIv3oegit
经过CMD命令行进入到该目录程序员
使用以下命令行导出.cs文件github
protogen.exe -i:Request.proto -o:Request.cs
命令解释编程
protogen -i:test.proto -o:test.cs -ns:UGE.Metadata -p:import=UGE 这句话的意思是, 输入test.proto文件, 给我生成 test.cs 文件, 代码在 namespace UGE.Metadata里, 顺便引用下 using UGE.
能够看到在同目录下生成了一个Request.cs文件,这个文件就是咱们想要的cs类文件c#
Request.cs文件内容以下markdown
可是这样一个一个的用命令行导出实在太麻烦,做为会偷懒的程序员,咱们要使用更快速的方式批量生成,这个时候咱们想到了BAT批处理
echo on set Path=ProtoGen\protogen.exe %Path% -i:Request.proto -o:OpenAPIModel\Request.cs %Path% -i:Response.proto -o:OpenAPIModel\Response.cs %Path% -i:UserInfo.proto -o:OpenAPIModel\UserInfo.cs %Path% -i:LoginReq.proto -o:OpenAPIModel\LoginReq.cs %Path% -i:LoginResp.proto -o:OpenAPIModel\LoginResp.cs pause
上面的批处理文件将全部的.proto文件到出成.cs类文件。
或者直接遍历某个文件夹下的全部.prot文件,所有转换
@echo off set Path=ProtoGen\protogen.exe for /f "delims=" %%i in ('dir /b proto "proto/*.proto"') do %Path% -i:proto/%%i -o:cs/%%~ni.cs pause
以上BAT以及demo的下载地址:http://pan.baidu.com/s/1pLtWTy7
搞定!
简介
Protobuf是google提供的一个开源序列化框架,相似于XML,JSON这样的数据表示语言。
支持多种编程语言,现:Java、c#、c++、Go 和 Python。
基于二进制,所以比传统的XML表示高效短小得多
做为一种效率和兼容性都很优秀的二进制数据传输格式,能够用于诸如网络传输、配置文件、数据存储等诸多领域。
使用
package 对应于c#中的命名空间
required 对应类的属性
optional 建立一个具备默认值的属性,经过[default=XXX]设置默认值,不添加默认为空置。如string默认为“”,int默认为0
enum 建立枚举
message 建立自定义类或内部类
repeated 对应list列表数据
proto数据类型:
示例:
package test; 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; }
proto文件编辑的命令:
protogen -i:input.proto -o:output.cs
protogen -i:input.proto -o:output.xml -t:xml
protogen -i:input.proto -o:output.cs -p:datacontract -q
protogen -i:input.proto -o:output.cs -p:observable=true
转换以后的文件:
//------------------------------------------------------------------------------ // <auto-generated> // This code was generated by a tool. // // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. // </auto-generated> //------------------------------------------------------------------------------ // Generated from: input/test.proto namespace input.test { [global::System.Serializable, global::ProtoBuf.ProtoContract(Name=@"Person")] public partial class Person : global::ProtoBuf.IExtensible { public Person() {} private string _name; [global::ProtoBuf.ProtoMember(1, IsRequired = true, Name=@"name", DataFormat = global::ProtoBuf.DataFormat.Default)] public string name { get { return _name; } set { _name = value; } } private int _id; [global::ProtoBuf.ProtoMember(2, IsRequired = true, Name=@"id", DataFormat = global::ProtoBuf.DataFormat.TwosComplement)] public int id { get { return _id; } set { _id = value; } } private string _email = ""; [global::ProtoBuf.ProtoMember(3, IsRequired = false, Name=@"email", DataFormat = global::ProtoBuf.DataFormat.Default)] [global::System.ComponentModel.DefaultValue("")] public string email { get { return _email; } set { _email = value; } } private readonly global::System.Collections.Generic.List<Person.PhoneNumber> _phone = new global::System.Collections.Generic.List<Person.PhoneNumber>(); [global::ProtoBuf.ProtoMember(4, Name=@"phone", DataFormat = global::ProtoBuf.DataFormat.Default)] public global::System.Collections.Generic.List<Person.PhoneNumber> phone { get { return _phone; } } [global::System.Serializable, global::ProtoBuf.ProtoContract(Name=@"PhoneNumber")] public partial class PhoneNumber : global::ProtoBuf.IExtensible { public PhoneNumber() {} private string _number; [global::ProtoBuf.ProtoMember(1, IsRequired = true, Name=@"number", DataFormat = global::ProtoBuf.DataFormat.Default)] public string number { get { return _number; } set { _number = value; } } private Person.PhoneType _type = Person.PhoneType.HOME; [global::ProtoBuf.ProtoMember(2, IsRequired = false, Name=@"type", DataFormat = global::ProtoBuf.DataFormat.TwosComplement)] [global::System.ComponentModel.DefaultValue(Person.PhoneType.HOME)] public Person.PhoneType type { get { return _type; } set { _type = value; } } private global::ProtoBuf.IExtension extensionObject; global::ProtoBuf.IExtension global::ProtoBuf.IExtensible.GetExtensionObject(bool createIfMissing) { return global::ProtoBuf.Extensible.GetExtensionObject(ref extensionObject, createIfMissing); } } [global::ProtoBuf.ProtoContract(Name=@"PhoneType")] public enum PhoneType { [global::ProtoBuf.ProtoEnum(Name=@"MOBILE", Value=0)] MOBILE = 0, [global::ProtoBuf.ProtoEnum(Name=@"HOME", Value=1)] HOME = 1, [global::ProtoBuf.ProtoEnum(Name=@"WORK", Value=2)] WORK = 2 } private global::ProtoBuf.IExtension extensionObject; global::ProtoBuf.IExtension global::ProtoBuf.IExtensible.GetExtensionObject(bool createIfMissing) { return global::ProtoBuf.Extensible.GetExtensionObject(ref extensionObject, createIfMissing); } } }
首先,将生成的.cs文件复制到本身的项目文件中
而后添加动态连接库文件protobuf-net.dll(该文件位于下载的proto文件的protobuf-net_r668\ProtoGen目录下)
而后在程序中引用,相关程序以下:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using ProtoBuf; using input.test; using System.IO; using System.Runtime.Serialization.Formatters.Binary; namespace test1 { class Program { static void Main(string[] args) { Person p = new Person(); p.name = "zhang san"; p.email = "XXXXX@qq.com"; p.id = 12; //序列化操做 MemoryStream ms=new MemoryStream(); //BinaryFormatter bm = new BinaryFormatter(); //bm.Serialize(ms, p); Serializer.Serialize<Person>(ms, p); byte[] data = ms.ToArray();//length=27 709 //反序列化操做 MemoryStream ms1 = new MemoryStream(data); // BinaryFormatter bm1 = new BinaryFormatter(); //Person p1= bm.Deserialize(ms1) as Person; Person p1 = Serializer.Deserialize<Person>(ms1); Console.ReadKey(); } } }