首页 > 代码库 > 项目中使用protobuf 3.0

项目中使用protobuf 3.0

protocol buffer从3.0 原生的compiler支持c++,Java,Python,Go,Ruby,JavaNano,JavaScript,Objective-C,C#,PHP这篇文章作为上一篇文章的补充,简单记录下一些变化。

protobuf的开源地址为:https://github.com/google/protobuf

protocol compiler下载地址为:https://github.com/google/protobuf/releases

官方定义message类型的例子:

syntax="proto3"

message SearchRequest{

  string query=1;

  int32 page_number=2;

  int32 result_per_page=3;

}

..proto文件的第一行指定使用proto3的语法。

 

特定语言的声明使用option关键定和选项名

option java_package="com.example.tutorial";//定义生成的java包

option java_outer_classname="AddressBookProtos";//定义java类名

option csharp_namespace="Google.Protobuf.Examples.AddressBook";//定义c#的命名空间

 

变化

1.字段前取消了required和optional两个关键字,目前可用的只有repeated关键字。

2.不可以现设置默认值了。

  a.string默认为空串

  b.枚举默认为第一个枚举定义的第一个值。并且必须是0

  c.bytes默认为空bytes

  d.bool默认为false

  e.数字类型默认为0

 

3.类型对应表

.proto TypeNotesC++ TypeJava TypePython Type[2]Go TypeRuby TypeC# TypePHP Type
double doubledoublefloatfloat64Floatdoublefloat
float floatfloatfloatfloat32Floatfloatfloat
int32Uses variable-length encoding. Inefficient for encoding negative numbers – if your field is likely to have negative values, use sint32 instead.int32intintint32Fixnum or Bignum (as required)intinteger
int64Uses variable-length encoding. Inefficient for encoding negative numbers – if your field is likely to have negative values, use sint64 instead.int64longint/long[3]int64Bignumlonginteger/string[5]
uint32Uses variable-length encoding.uint32int[1]int/long[3]uint32Fixnum or Bignum (as required)uintinteger
uint64Uses variable-length encoding.uint64long[1]int/long[3]uint64Bignumulonginteger/string[5]
sint32Uses variable-length encoding. Signed int value. These more efficiently encode negative numbers than regular int32s.int32intintint32Fixnum or Bignum (as required)intinteger
sint64Uses variable-length encoding. Signed int value. These more efficiently encode negative numbers than regular int64s.int64longint/long[3]int64Bignumlonginteger/string[5]
fixed32Always four bytes. More efficient than uint32 if values are often greater than 228.uint32int[1]intuint32Fixnum or Bignum (as required)uintinteger
fixed64Always eight bytes. More efficient than uint64 if values are often greater than 256.uint64long[1]int/long[3]uint64Bignumulonginteger/string[5]
sfixed32Always four bytes.int32intintint32Fixnum or Bignum (as required)intinteger
sfixed64Always eight bytes.int64longint/long[3]int64Bignumlonginteger/string[5]
bool boolbooleanboolboolTrueClass/FalseClassboolboolean
stringA string must always contain UTF-8 encoded or 7-bit ASCII text.stringStringstr/unicode[4]stringString (UTF-8)stringstring
bytesMay contain any arbitrary sequence of bytes.stringByteStringstr[]byteString (ASCII-8BIT)ByteStringstring

 

proto代码编译

语法:

protoc --proto_path=IMPORT_PATH --cpp_out=DST_DIR --java_out=DST_DIR --python_out=DST_DIR --go_out=DST_DIR --ruby_out=DST_DIR --javanano_out=DST_DIR --objc_out=DST_DIR --csharp_out=DST_DIR path/to/file.proto

--proto_path 当proto文件中使用import时指定的导入文件的位置

--cpp_out c++输出目录

--java_out java输出目录

--python_out

--go_out

--ruby_out ruby输出目录

--objc_out oc输出目录

--csharp_out c#输出目录

path/to/file.proto为要编译的proto文件

使用

proto内容:

syntax="proto3";

option java_package="com.ztimage";
option java_outer_classname="WebUI";
option csharp_namespace="ZTImage.WebUI";
message SearchRequest{
string query=1;
int32 page_number=2;
int32 result_per_page=3;
}

 

执行命令:protoc --csharp_out d:/programs/protoc/bin WebUI.proto

生成代码:

技术分享
// Generated by the protocol buffer compiler.  DO NOT EDIT!// source: WebUI.proto#pragma warning disable 1591, 0612, 3021#region Designer generated codeusing pb = global::Google.Protobuf;using pbc = global::Google.Protobuf.Collections;using pbr = global::Google.Protobuf.Reflection;using scg = global::System.Collections.Generic;namespace ZTImage.WebUI {  /// <summary>Holder for reflection information generated from WebUI.proto</summary>  public static partial class WebUIReflection {    #region Descriptor    /// <summary>File descriptor for WebUI.proto</summary>    public static pbr::FileDescriptor Descriptor {      get { return descriptor; }    }    private static pbr::FileDescriptor descriptor;    static WebUIReflection() {      byte[] descriptorData = http://www.mamicode.com/global::System.Convert.FromBase64String(          string.Concat(            "CgtXZWJVSS5wcm90byJMCg1TZWFyY2hSZXF1ZXN0Eg0KBXF1ZXJ5GAEgASgJ",            "EhMKC3BhZ2VfbnVtYmVyGAIgASgFEhcKD3Jlc3VsdF9wZXJfcGFnZRgDIAEo",            "BUIkCgtjb20uenRpbWFnZUIFV2ViVUmqAg1aVEltYWdlLldlYlVJYgZwcm90",            "bzM="));      descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData,          new pbr::FileDescriptor[] { },          new pbr::GeneratedClrTypeInfo(null, new pbr::GeneratedClrTypeInfo[] {            new pbr::GeneratedClrTypeInfo(typeof(global::ZTImage.WebUI.SearchRequest), global::ZTImage.WebUI.SearchRequest.Parser, new[]{ "Query", "PageNumber", "ResultPerPage" }, null, null, null)          }));    }    #endregion  }  #region Messages  public sealed partial class SearchRequest : pb::IMessage<SearchRequest> {    private static readonly pb::MessageParser<SearchRequest> _parser = new pb::MessageParser<SearchRequest>(() => new SearchRequest());    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]    public static pb::MessageParser<SearchRequest> Parser { get { return _parser; } }    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]    public static pbr::MessageDescriptor Descriptor {      get { return global::ZTImage.WebUI.WebUIReflection.Descriptor.MessageTypes[0]; }    }    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]    pbr::MessageDescriptor pb::IMessage.Descriptor {      get { return Descriptor; }    }    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]    public SearchRequest() {      OnConstruction();    }    partial void OnConstruction();    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]    public SearchRequest(SearchRequest other) : this() {      query_ = other.query_;      pageNumber_ = other.pageNumber_;      resultPerPage_ = other.resultPerPage_;    }    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]    public SearchRequest Clone() {      return new SearchRequest(this);    }    /// <summary>Field number for the "query" field.</summary>    public const int QueryFieldNumber = 1;    private string query_ = "";    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]    public string Query {      get { return query_; }      set {        query_ = pb::ProtoPreconditions.CheckNotNull(value, "value");      }    }    /// <summary>Field number for the "page_number" field.</summary>    public const int PageNumberFieldNumber = 2;    private int pageNumber_;    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]    public int PageNumber {      get { return pageNumber_; }      set {        pageNumber_ = value;      }    }    /// <summary>Field number for the "result_per_page" field.</summary>    public const int ResultPerPageFieldNumber = 3;    private int resultPerPage_;    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]    public int ResultPerPage {      get { return resultPerPage_; }      set {        resultPerPage_ = value;      }    }    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]    public override bool Equals(object other) {      return Equals(other as SearchRequest);    }    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]    public bool Equals(SearchRequest other) {      if (ReferenceEquals(other, null)) {        return false;      }      if (ReferenceEquals(other, this)) {        return true;      }      if (Query != other.Query) return false;      if (PageNumber != other.PageNumber) return false;      if (ResultPerPage != other.ResultPerPage) return false;      return true;    }    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]    public override int GetHashCode() {      int hash = 1;      if (Query.Length != 0) hash ^= Query.GetHashCode();      if (PageNumber != 0) hash ^= PageNumber.GetHashCode();      if (ResultPerPage != 0) hash ^= ResultPerPage.GetHashCode();      return hash;    }    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]    public override string ToString() {      return pb::JsonFormatter.ToDiagnosticString(this);    }    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]    public void WriteTo(pb::CodedOutputStream output) {      if (Query.Length != 0) {        output.WriteRawTag(10);        output.WriteString(Query);      }      if (PageNumber != 0) {        output.WriteRawTag(16);        output.WriteInt32(PageNumber);      }      if (ResultPerPage != 0) {        output.WriteRawTag(24);        output.WriteInt32(ResultPerPage);      }    }    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]    public int CalculateSize() {      int size = 0;      if (Query.Length != 0) {        size += 1 + pb::CodedOutputStream.ComputeStringSize(Query);      }      if (PageNumber != 0) {        size += 1 + pb::CodedOutputStream.ComputeInt32Size(PageNumber);      }      if (ResultPerPage != 0) {        size += 1 + pb::CodedOutputStream.ComputeInt32Size(ResultPerPage);      }      return size;    }    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]    public void MergeFrom(SearchRequest other) {      if (other == null) {        return;      }      if (other.Query.Length != 0) {        Query = other.Query;      }      if (other.PageNumber != 0) {        PageNumber = other.PageNumber;      }      if (other.ResultPerPage != 0) {        ResultPerPage = other.ResultPerPage;      }    }    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]    public void MergeFrom(pb::CodedInputStream input) {      uint tag;      while ((tag = input.ReadTag()) != 0) {        switch(tag) {          default:            input.SkipLastField();            break;          case 10: {            Query = input.ReadString();            break;          }          case 16: {            PageNumber = input.ReadInt32();            break;          }          case 24: {            ResultPerPage = input.ReadInt32();            break;          }        }      }    }  }  #endregion}#endregion Designer generated code
View Code

在项目中引用Google.Protobuf程序集,生成的代码放到项目中

测试代码:

技术分享
using System;using System.Collections.Generic;using System.IO;using System.Linq;using System.Text;using System.Threading.Tasks;using Google.Protobuf;namespace ZTImage.WebUI{    class Program    {        static void Main(string[] args)        {            SearchRequest request = new SearchRequest() {                Query="age>0 and age <18",                PageNumber=1,                ResultPerPage=50            };            using (var output = File.Create("mr.dat"))            {                request.WriteTo(output);            }            SearchRequest sr = null;            using (var input = File.OpenRead("mr.dat"))            {                sr = SearchRequest.Parser.ParseFrom(input);            }            Console.WriteLine("Query:{0},PageNumber:{1},ResultPerPage:{2}",sr.Query,sr.PageNumber,sr.ResultPerPage);            Console.ReadKey();                                                }    }}
View Code

结果:

Query:age>0 and age <18,PageNumber:1,ResultPerPage:50

pref:

500W writer 2022ms read 1864ms

 

项目中使用protobuf 3.0