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(); } } }