项目中使用protobuf 3.0

时间:2023-03-09 21:49:10
项目中使用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 Type Notes C++ Type Java Type Python Type[2] Go Type Ruby Type C# Type PHP Type
double   double double float float64 Float double float
float   float float float float32 Float float float
int32 Uses variable-length encoding. Inefficient for encoding negative numbers – if your field is likely to have negative values, use sint32 instead. int32 int int int32 Fixnum or Bignum (as required) int integer
int64 Uses variable-length encoding. Inefficient for encoding negative numbers – if your field is likely to have negative values, use sint64 instead. int64 long int/long[3] int64 Bignum long integer/string[5]
uint32 Uses variable-length encoding. uint32 int[1] int/long[3] uint32 Fixnum or Bignum (as required) uint integer
uint64 Uses variable-length encoding. uint64 long[1] int/long[3] uint64 Bignum ulong integer/string[5]
sint32 Uses variable-length encoding. Signed int value. These more efficiently encode negative numbers than regular int32s. int32 int int int32 Fixnum or Bignum (as required) int integer
sint64 Uses variable-length encoding. Signed int value. These more efficiently encode negative numbers than regular int64s. int64 long int/long[3] int64 Bignum long integer/string[5]
fixed32 Always four bytes. More efficient than uint32 if values are often greater than 228. uint32 int[1] int uint32 Fixnum or Bignum (as required) uint integer
fixed64 Always eight bytes. More efficient than uint64 if values are often greater than 256. uint64 long[1] int/long[3] uint64 Bignum ulong integer/string[5]
sfixed32 Always four bytes. int32 int int int32 Fixnum or Bignum (as required) int integer
sfixed64 Always eight bytes. int64 long int/long[3] int64 Bignum long integer/string[5]
bool   bool boolean bool bool TrueClass/FalseClass bool boolean
string A string must always contain UTF-8 encoded or 7-bit ASCII text. string String str/unicode[4] string String (UTF-8) string string
bytes May contain any arbitrary sequence of bytes. string ByteString str []byte String (ASCII-8BIT) ByteString string

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 code using 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 = 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[]; }
} [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 = ;
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 = ;
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 = ;
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 = ;
if (Query.Length != ) hash ^= Query.GetHashCode();
if (PageNumber != ) hash ^= PageNumber.GetHashCode();
if (ResultPerPage != ) 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 != ) {
output.WriteRawTag();
output.WriteString(Query);
}
if (PageNumber != ) {
output.WriteRawTag();
output.WriteInt32(PageNumber);
}
if (ResultPerPage != ) {
output.WriteRawTag();
output.WriteInt32(ResultPerPage);
}
} [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public int CalculateSize() {
int size = ;
if (Query.Length != ) {
size += + pb::CodedOutputStream.ComputeStringSize(Query);
}
if (PageNumber != ) {
size += + pb::CodedOutputStream.ComputeInt32Size(PageNumber);
}
if (ResultPerPage != ) {
size += + pb::CodedOutputStream.ComputeInt32Size(ResultPerPage);
}
return size;
} [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public void MergeFrom(SearchRequest other) {
if (other == null) {
return;
}
if (other.Query.Length != ) {
Query = other.Query;
}
if (other.PageNumber != ) {
PageNumber = other.PageNumber;
}
if (other.ResultPerPage != ) {
ResultPerPage = other.ResultPerPage;
}
} [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public void MergeFrom(pb::CodedInputStream input) {
uint tag;
while ((tag = input.ReadTag()) != ) {
switch(tag) {
default:
input.SkipLastField();
break;
case : {
Query = input.ReadString();
break;
}
case : {
PageNumber = input.ReadInt32();
break;
}
case : {
ResultPerPage = input.ReadInt32();
break;
}
}
}
} } #endregion } #endregion Designer generated 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=,
ResultPerPage=
}; 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(); }
}
}

结果:

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

pref:

500W writer 2022ms read 1864ms