简介
Protobuf是google提供的一个开源序列化框架,类似于XML,JSON这样的数据表示语言。
支持多种编程语言,现:Java、c#、c++、go 和 Python。
基于二进制,因此比传统的XML表示高效短小得多
作为一种效率和兼容性都很优秀的二进制数据传输格式,可以用于诸如网络传输、配置文件、数据存储等诸多领域。
使用
1、下载地址:http://code.google.com/p/protobuf/downloads/
2、proto文件格式
package 对应于c#中的命名空间
required 对应类的属性
optional 创建一个具有默认值的属性,通过[default=XXX]设置默认值,不添加默认为空置。如string默认为“”,int默认为0
enum 创建枚举
message 创建自定义类或内部类
repeated 对应list列表数据
proto数据类型:
示例:
<code class="hljs go has-numbering"><span class="hljs-keyword">package</span> test; message Person { required <span class="hljs-typename">string</span> name<span class="hljs-number">=1</span>; required <span class="hljs-typename">int32</span> id<span class="hljs-number">=2</span>; optional <span class="hljs-typename">string</span> email<span class="hljs-number">=3</span> ; enum PhoneType { MOBILE<span class="hljs-number">=0</span>; HOME<span class="hljs-number">=1</span>; WORK<span class="hljs-number">=2</span>; } message PhoneNumber { required <span class="hljs-typename">string</span> number<span class="hljs-number">=1</span>; optional PhoneType <span class="hljs-keyword">type</span><span class="hljs-number">=2</span> [<span class="hljs-keyword">default</span>=HOME]; } repeated PhoneNumber phone<span class="hljs-number">=4</span>; }</code>
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
转换之后的文件:
<code class="hljs cs has-numbering"><span class="hljs-comment">//------------------------------------------------------------------------------</span> <span class="hljs-comment">// <auto-generated></span> <span class="hljs-comment">// This code was generated by a tool.</span> <span class="hljs-comment">//</span> <span class="hljs-comment">// Changes to this file may cause incorrect behavior and will be lost if</span> <span class="hljs-comment">// the code is regenerated.</span> <span class="hljs-comment">// </auto-generated></span> <span class="hljs-comment">//------------------------------------------------------------------------------</span> <span class="hljs-comment">// Generated from: input/test.proto</span> namespace input.test { [global::System.Serializable, global::ProtoBuf.ProtoContract(Name=<span class="hljs-string">@"Person"</span>)] <span class="hljs-keyword">public</span> <span class="hljs-keyword">partial</span> <span class="hljs-keyword">class</span> Person : global::ProtoBuf.IExtensible { <span class="hljs-keyword">public</span> <span class="hljs-title">Person</span>() {} <span class="hljs-keyword">private</span> <span class="hljs-keyword">string</span> _name; [global::ProtoBuf.ProtoMember(<span class="hljs-number">1</span>, IsRequired = <span class="hljs-keyword">true</span>, Name=<span class="hljs-string">@"name"</span>, DataFormat = global::ProtoBuf.DataFormat.Default)] <span class="hljs-keyword">public</span> <span class="hljs-keyword">string</span> name { <span class="hljs-keyword">get</span> { <span class="hljs-keyword">return</span> _name; } <span class="hljs-keyword">set</span> { _name = <span class="hljs-keyword">value</span>; } } <span class="hljs-keyword">private</span> <span class="hljs-keyword">int</span> _id; [global::ProtoBuf.ProtoMember(<span class="hljs-number">2</span>, IsRequired = <span class="hljs-keyword">true</span>, Name=<span class="hljs-string">@"id"</span>, DataFormat = global::ProtoBuf.DataFormat.TwosComplement)] <span class="hljs-keyword">public</span> <span class="hljs-keyword">int</span> id { <span class="hljs-keyword">get</span> { <span class="hljs-keyword">return</span> _id; } <span class="hljs-keyword">set</span> { _id = <span class="hljs-keyword">value</span>; } } <span class="hljs-keyword">private</span> <span class="hljs-keyword">string</span> _email = <span class="hljs-string">""</span>; [global::ProtoBuf.ProtoMember(<span class="hljs-number">3</span>, IsRequired = <span class="hljs-keyword">false</span>, Name=<span class="hljs-string">@"email"</span>, DataFormat = global::ProtoBuf.DataFormat.Default)] [global::System.ComponentModel.DefaultValue(<span class="hljs-string">""</span>)] <span class="hljs-keyword">public</span> <span class="hljs-keyword">string</span> email { <span class="hljs-keyword">get</span> { <span class="hljs-keyword">return</span> _email; } <span class="hljs-keyword">set</span> { _email = <span class="hljs-keyword">value</span>; } } <span class="hljs-keyword">private</span> <span class="hljs-keyword">readonly</span> global::System.Collections.Generic.List<Person.PhoneNumber> _phone = <span class="hljs-keyword">new</span> global::System.Collections.Generic.List<Person.PhoneNumber>(); [global::ProtoBuf.ProtoMember(<span class="hljs-number">4</span>, Name=<span class="hljs-string">@"phone"</span>, DataFormat = global::ProtoBuf.DataFormat.Default)] <span class="hljs-keyword">public</span> global::System.Collections.Generic.List<Person.PhoneNumber> phone { <span class="hljs-keyword">get</span> { <span class="hljs-keyword">return</span> _phone; } } [global::System.Serializable, global::ProtoBuf.ProtoContract(Name=<span class="hljs-string">@"PhoneNumber"</span>)] <span class="hljs-keyword">public</span> <span class="hljs-keyword">partial</span> <span class="hljs-keyword">class</span> PhoneNumber : global::ProtoBuf.IExtensible { <span class="hljs-keyword">public</span> <span class="hljs-title">PhoneNumber</span>() {} <span class="hljs-keyword">private</span> <span class="hljs-keyword">string</span> _number; [global::ProtoBuf.ProtoMember(<span class="hljs-number">1</span>, IsRequired = <span class="hljs-keyword">true</span>, Name=<span class="hljs-string">@"number"</span>, DataFormat = global::ProtoBuf.DataFormat.Default)] <span class="hljs-keyword">public</span> <span class="hljs-keyword">string</span> number { <span class="hljs-keyword">get</span> { <span class="hljs-keyword">return</span> _number; } <span class="hljs-keyword">set</span> { _number = <span class="hljs-keyword">value</span>; } } <span class="hljs-keyword">private</span> Person.PhoneType _type = Person.PhoneType.HOME; [global::ProtoBuf.ProtoMember(<span class="hljs-number">2</span>, IsRequired = <span class="hljs-keyword">false</span>, Name=<span class="hljs-string">@"type"</span>, DataFormat = global::ProtoBuf.DataFormat.TwosComplement)] [global::System.ComponentModel.DefaultValue(Person.PhoneType.HOME)] <span class="hljs-keyword">public</span> Person.PhoneType type { <span class="hljs-keyword">get</span> { <span class="hljs-keyword">return</span> _type; } <span class="hljs-keyword">set</span> { _type = <span class="hljs-keyword">value</span>; } } <span class="hljs-keyword">private</span> global::ProtoBuf.IExtension extensionObject; global::ProtoBuf.IExtension global::ProtoBuf.IExtensible.GetExtensionObject(<span class="hljs-keyword">bool</span> createIfMissing) { <span class="hljs-keyword">return</span> global::ProtoBuf.Extensible.GetExtensionObject(<span class="hljs-keyword">ref</span> extensionObject, createIfMissing); } } [global::ProtoBuf.ProtoContract(Name=<span class="hljs-string">@"PhoneType"</span>)] <span class="hljs-keyword">public</span> <span class="hljs-keyword">enum</span> PhoneType { [global::ProtoBuf.ProtoEnum(Name=<span class="hljs-string">@"MOBILE"</span>, Value=<span class="hljs-number">0</span>)] MOBILE = <span class="hljs-number">0</span>, [global::ProtoBuf.ProtoEnum(Name=<span class="hljs-string">@"HOME"</span>, Value=<span class="hljs-number">1</span>)] HOME = <span class="hljs-number">1</span>, [global::ProtoBuf.ProtoEnum(Name=<span class="hljs-string">@"WORK"</span>, Value=<span class="hljs-number">2</span>)] WORK = <span class="hljs-number">2</span> } <span class="hljs-keyword">private</span> global::ProtoBuf.IExtension extensionObject; global::ProtoBuf.IExtension global::ProtoBuf.IExtensible.GetExtensionObject(<span class="hljs-keyword">bool</span> createIfMissing) { <span class="hljs-keyword">return</span> global::ProtoBuf.Extensible.GetExtensionObject(<span class="hljs-keyword">ref</span> extensionObject, createIfMissing); } } }</code>
3、proto转化后的.cs文件的序列化和反序列化
首先,将生成的.cs文件复制到自己的项目文件中
然后添加动态链接库文件protobuf-net.dll(该文件位于下载的proto文件的protobuf-net_r668\ProtoGen目录下)
然后在程序中引用,相关程序如下:
<code class="hljs vala has-numbering"><span class="hljs-keyword">using</span> System; <span class="hljs-keyword">using</span> System.Collections.Generic; <span class="hljs-keyword">using</span> System.Linq; <span class="hljs-keyword">using</span> System.Text; <span class="hljs-keyword">using</span> System.Threading.Tasks; <span class="hljs-keyword">using</span> ProtoBuf; <span class="hljs-keyword">using</span> input.test; <span class="hljs-keyword">using</span> System.IO; <span class="hljs-keyword">using</span> System.Runtime.Serialization.Formatters.Binary; <span class="hljs-class"><span class="hljs-keyword">namespace</span> <span class="hljs-title">test1</span> {</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Program</span> {</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> Main(<span class="hljs-keyword">string</span>[] args) { Person p = <span class="hljs-keyword">new</span> Person(); p.name = <span class="hljs-string">"zhang san"</span>; p.email = <span class="hljs-string">"XXXXX@qq.com"</span>; p.id = <span class="hljs-number">12</span>; <span class="hljs-comment">//序列化操作</span> MemoryStream ms=<span class="hljs-keyword">new</span> MemoryStream(); <span class="hljs-comment">//BinaryFormatter bm = new BinaryFormatter();</span> <span class="hljs-comment">//bm.Serialize(ms, p);</span> Serializer.Serialize<Person>(ms, p); byte[] data = ms.ToArray();<span class="hljs-comment">//length=27 709</span> <span class="hljs-comment">//反序列化操作</span> MemoryStream ms1 = <span class="hljs-keyword">new</span> MemoryStream(data); <span class="hljs-comment">// BinaryFormatter bm1 = new BinaryFormatter();</span> <span class="hljs-comment">//Person p1= bm.Deserialize(ms1) as Person;</span> Person p1 = Serializer.Deserialize<Person>(ms1); Console.ReadKey(); } } }</code>