c# 中针对Protobuf的应用,使用Protobuf-net序列化和反序列化数据

c# 中针对Protobuf的应用

Protobuf介绍

Protobuf是Protocol buffers的简称,是由Google公司推出的一种数据交换格式,与传统的xml、json有着相同的作用,相对于xml和Json的区别是,Protobuf省略了数据的自描述所以数据更小,采用的是二进制的数据格式所以有很高的转换效率。同时也支持多种编程语言兼容。是用于数据传递,数据存储的一种较好方式。

Protobuf语法

protobuf协议文件是以.proto结尾的文本文件。

syntax = "proto3";
package ProtoBuffTest;

message DataItem {
   string ID = 1;
   repeated string IDArray = 2;
}
message DataStruct {
   string ID = 1;
   string Name = 2;
   repeated int32 Numbers = 3 [packed = false];
   repeated uint32 Buffer = 4 [packed = false];
   DataItem DataItem = 5;
   repeated DataItem DataItems = 6;
   repeated int32 Ints = 7 [packed = false];
   bytes Bytes = 8;
   DataType dataType = 9;
}
enum DataType {
   Byte = 0;
   Short = 1;
}

标识符

  • syntax:标识使用的protobuf是哪个版本。上面表示使用的是3.x版本。
  • package:标识生成目标文件的包名。在C#、C++中表示的是命名空间。java 等语言中表示的是包名
  • enum:表示一个枚举类型。会在目标.h文件中自动生成一个枚举类型。
  • message:标识一条消息。会在目标文件中自动生成一个类。

字段

  1. 字段格式:
role type name = tag [default value]
  1. role 有三种取值:
  • required:该字段必须给值,不能为空。否则message被认为是未初始化的。如果试图建立一个未初始化的message将会抛出RuntimeException异常,解析未初始化的message会抛出IOException异常。

  • optional:表示该字段是可选值,可以为空。如果不设置,会设置一个默认值。也可以自定义默认值。如果没有自定义默认值,会是用系统默认值。

  • repeated:表示该字段可以重复,可等同于动态数组。
    注意:required字段是永久性的,如果之后不使用该字段,或者该字段标识改为optional或repeated,那么使用就接口读取新协议时,如果发现没有该字段,会认为该消息不完整,会拒收或者丢弃该消息。

字段类型

Protobuf数据类型描述
bool布尔类型
double64位浮点数​
float32为浮点数​
int3232位整数、​
uin32无符号32位整数​
int6464位整数​
uint6464为无符号整​
sint3232位整数,处理负数率更高​
fixed3264位整数处理负数效率更高​
fixed3232位无符号整数​
fixed6464位无符号整数​
sfixed3232位整数、能以更高的效率处理负数​
sfixed6464为整数​
string只能处理ASCII字符​
bytes用于处理多字节的语言字符、如中文​
enum可以包含一个用户自定义的枚举类型uint32​
message可以包含一个用户自定义的消息类型

C#中针对Protobuf的使用

在C#中可以使用March Gravel提供的C#库Protobuf-net来完成对Protobuf数据结构的应用。

基本用法

  1. 定义Protobuf数据结构
[ProtoContract]
public class DataStruct
{
	[ProtoMember(1)]
	public string ID { get; set; }
	[ProtoMember(2)]
	public string Name { get; set; }
	[ProtoMember(3)]
	public List<int> Numbers { get; set; }
	[ProtoMember(4)]
	public List<byte> Buffer { get; set; }
	[ProtoMember(5)]
	public DataItem DataItem { get; set; }
	[ProtoMember(6)]
	public List<DataItem> DataItems { get; set; }
	[ProtoMember(7)]
	public int[] Ints { get; set; }
	[ProtoMember(8)]
	public byte[] Bytes { get; set; }
	[ProtoMember(9)]
	public DataType dataType { get; set; }
}

[ProtoContract]
public enum DataType
{
	[ProtoMember(1)]
	Byte = 0,
	[ProtoMember(2)]
	Short = 1
}

[ProtoContract]
public class DataItem
{
	[ProtoMember(1)]
	public string ID { get; set; } = "";
	[ProtoMember(2)]
	public List<string> IDArray { get; set; } = new List<string>();
}
  1. 导出Proto代码
	 SchemaGenerationOptions options =new SchemaGenerationOptions();
	 options.Types.Add(typeof(DataStruct));
	 options.Types.Add(typeof(DataItem));
	 options.Types.Add(typeof(DataType));
	 var proto = Serializer.GetProto(options);
	 Console.WriteLine(proto);
  1. 序列化数据
 public static byte[] ToBytes(object obj)
 {
 	try{
 		using(MemoryStream ms=new MemoryStream )
 		{
 			Serializer.Serialize(ms,obj);
 			var buffer=ms.GetBuffer();
 			var dataBuffer=new byte[ms.Length];
 			Array.Copy(buffer,dataBuffer,ms.Length);
 			ms.Dispose();
 			return dataBuffer;
 		}
 	}catch{
 	  return null;
 	}
 }
 
  1. 反序列化数据
public static T ToObj<T>(byte[] bufferData)
{
if (bufferData == null)
{
return default;
}
try{
	using( MemoryStream ms= new MemoryStream ())
	{
	ms.SetLength(bufferData.Length);
	ms.Write(bufferData, 0, bufferData.Length);
	ms.Position = 0L;memoryStream.Flush();
	T result = Serializer.Deserialize<T>(memoryStream);
	ms.Dispose();
	return result;
	}
}catch
{
	return default;
}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值