美文网首页
Unity高级-数据序列化-ProroBuf

Unity高级-数据序列化-ProroBuf

作者: passiony | 来源:发表于2018-05-29 15:46 被阅读275次

Protobuf

protocolbuffer(以下简称PB)是google 的一种数据交换的格式,它独立于语言,独立于平台。
google 提供了多种语言的实现:java、c#、c++、go 和 python,每一种实现都包含了相应语言的编译器以及库文件。
由于它是一种二进制的格式,比使用xml 进行数据交换快许多。可以把它用于分布式应用之间的数据通信或者异构环境下的数据交换。
作为一种效率和兼容性都很优秀的二进制数据传输格式,可以用于诸如网络传输、配置文件、数据存储等诸多领域。

将protobuf的消息体导出成C#支持的.cs类

protobufgen.exe
  • 2.使用如下命令行导出.cs文件
    protogen.exe -i:Request.proto -o:Request.cs
    命令解释
    protogen -i:test.proto -o:test.cs -ns:UGE.Metadata -p:import=UGE
    输入(input)test.proto文件, 输出(output) test.cs 文件, 代码在 namespace UGE.Metadata里, 顺便引用下 using UGE.

  • 3.可以看到在同目录下生成了一个Request.cs文件,这个文件就是我们想要的cs类文件


    Request.cs
  • 4.扩展(批处理代码)
    下面的批处理文件将所有的.proto文件到出成.cs类文件。

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类文件。

@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

proto文件格式

package 对应于c#中的命名空间
required 对应类的属性
optional 创建一个具有默认值的属性,通过[default=XXX]设置默认值,不添加默认为空置。如string默认为“”,int默认为0
enum 创建枚举
message 创建自定义类或内部类
repeated 对应list列表数据

proto数据类型:


proto数据类型.png

示例:

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

转换之后的文件:Percen.cs

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

proto转化后的.cs文件的序列化和反序列化

首先,将生成的.cs文件复制到自己的项目文件中
然后添加动态链接库文件protobuf-net.dll(该文件位于下载的proto文件的protobuf-net_r668\ProtoGen目录下)
然后在程序中引用,相关程序如下:

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

相关文章

网友评论

      本文标题:Unity高级-数据序列化-ProroBuf

      本文链接:https://www.haomeiwen.com/subject/xplajftx.html