zoukankan      html  css  js  c++  java
  • C#使用protobuf

    C# protobuf的使用方法  

    通过.proto文件导出C#支持的.cs类文件

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

    github上相关开源项目代码:http://pan.baidu.com/s/1eSDSb5o

    下面演示如何将protobuf的消息体导出成C#支持的.cs类

    首先我们获取到如下.proto文件

    复制代码
    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/1eRIv3oe

    通过CMD命令行进入到该目录

     使用如下命令行导出.cs文件

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

    Request.cs文件内容如下

     View Code

    但是这样一个一个的用命令行导出实在太麻烦,作为会偷懒的程序员,我们要使用更快速的方式批量生成,这个时候我们想到了BAT批处理

    复制代码
    echo on
    
    set Path=ProtoGenprotogen.exe
    
     
    %Path%  -i:Request.proto    -o:OpenAPIModelRequest.cs
    
    %Path%  -i:Response.proto    -o:OpenAPIModelResponse.cs
    
    %Path%  -i:UserInfo.proto    -o:OpenAPIModelUserInfo.cs
    
    %Path%  -i:LoginReq.proto    -o:OpenAPIModelLoginReq.cs
    
    %Path%  -i:LoginResp.proto    -o:OpenAPIModelLoginResp.cs
    
    pause
    复制代码

    上面的批处理文件将所有的.proto文件到出成.cs类文件。

    或者直接遍历某个文件夹下的所有.prot文件,全部转换

    复制代码
    @echo off
    
    set Path=ProtoGenprotogen.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表示高效短小得多 
    作为一种效率和兼容性都很优秀的二进制数据传输格式,可以用于诸如网络传输、配置文件、数据存储等诸多领域。 
    使用

    1、下载地址:http://code.google.com/p/protobuf/downloads/

    2、proto文件格式

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

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

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

    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();
            }
        }
    }
     
     
  • 相关阅读:
    Nginx练习练习玩玩
    MySQL Lock--MySQL加锁规则
    MySQL Transaction--RR事务隔离级别下加锁测试
    MySQL Transaction--RC事务隔离级别下加锁测试
    MySQL Transaction--事务隔离级别基础
    MySQL Transaction--快照读和当前读
    MySQL Transaction--RC和RR区别
    MySQL Disk--NAND Flash原理
    MySQL Disk--SSD与RAID
    MySQL Disk--SSD磁盘性能抖动问题
  • 原文地址:https://www.cnblogs.com/Leo_wl/p/7126321.html
Copyright © 2011-2022 走看看