ProtoBuf使用说明
Posted HiveDark
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ProtoBuf使用说明相关的知识,希望对你有一定的参考价值。
一、Protobuf简介
protobuf(Google Protocol Buffers)是Google提供一个具有高效的协议数据交换格式工具库(类似Json),但相比于Json,Protobuf有更高的转化效率,时间效率和空间效率都是JSON的3-5倍。参考GitHub
二、安装Protobuf环境
- windows环境下载
protoc-2.5.0-win32.zip
,下载后解压将protoc.exe
拷贝至C:\\Windows\\System32
目录下即可使用。 - linux环境下在
protobuf-2.5.0.tar.gz
,解压后参考README.txt
安装环境。
三、protobuf语法介绍
- message:代表了实体结构,由多个消息字段(field)组成。
- 消息字段(field): 包括数据类型、字段名、字段规则、字段唯一标识、默认值。
- 数据类型:常见的原子类型都支持(在FieldDescriptor::kTypeToName中有定义)
- 字段规则:(在FieldDescriptor::kLabelToName中定义)
required:必须初始化字段,如果没有赋值,在数据序列化时会抛出异常
optional:可选字段,可以不必初始化。
repeated:数据可以重复(相当于java 中的Array或List)
字段唯一标识:序列化和反序列化将会使用到。
- 默认值:在定义消息字段时可以给出默认值。
四、编写.proto文件
//指定protobuf语法版本
syntax = "proto2";
//包名
option java_package = "com.lhc.protobuf";
//源文件类名
option java_outer_classname = "AddressBookProtos";
// class Person
message Person
//required 必须设置(不能为null)
required string name = 1;
//int32 对应java中的int
required int32 id = 2;
//optional 可以为空
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 重复的 (集合)
repeated PhoneNumber phones = 4;
message AddressBook
repeated Person people = 1;
五、生成java文件
windows下打开cmd窗口,执行命令protoc -I=proto文件所在目录 --java_out=java文件生成的根目录(通常src/main/java) proto文件的绝对路径
eg:protoc -I=src/main/resources/proto --java_out=src/main/java src/main/resources/proto/ProtoBufHeader.proto
生成后的文件在src/main/java目录下,可在.proto文件中定义包名。
六、使用生成的java文件
@Test
public void test()
//包头
ProtoBufMsg.HsHeaderMsg.Builder headerBuilder = ProtoBufMsg.HsHeaderMsg.newBuilder();
headerBuilder.setSrcAddr("192.168.0.1");
headerBuilder.setDestAddr("127.0.0.1");
headerBuilder.setAckFlag(true);
headerBuilder.setSeqNo(3);
headerBuilder.setTerminalType(1);
headerBuilder.setPlatFormType(1);
HsHeaderMsg hsHeaderMsg = headerBuilder.build();
//消息实体
ProtoBufMsg.BusArrLeftMsg.Builder builder = ProtoBufMsg.BusArrLeftMsg.newBuilder();
builder.setHeader(hsHeaderMsg);
builder.setAngle(30);
builder.setAvgSpeed(55.5);
builder.setLongitude(138.11111);
builder.setLatitude(29.33333);
builder.setMsgTime("2020-12-31 11:11:00");
builder.setRouteID("6");
builder.setProductID("1");
builder.setDualSerialid("1");
builder.setIsArrLeft("1");
//data
BusArrLeftMsg data = builder.build();
//输出对象数据
System.out.println(data.toString());
System.out.println("===== gps Byte 开始=====");
for(byte b : data.toByteArray())
System.out.print(b);
System.out.println("\\n" + "bytes长度" + data.toByteString().size());
System.out.println("===== gps Byte 结束 =====");
System.out.println("===== 使用gps 反序列化生成对象开始 =====");
BusArrLeftMsg gd = null;
try
gd = ProtoBufMsg.BusArrLeftMsg.parseFrom(data.toByteArray());
catch (InvalidProtocolBufferException e)
e.printStackTrace();
System.out.print(gd.toString());
System.out.println("===== 使用gps 反序列化生成对象结束 =====");
七、单元测试输出结果
Header
SrcAddr: "192.168.0.1"
DestAddr: "127.0.0.1"
AckFlag: true
SeqNo: 3
TerminalType: 1
PlatFormType: 1
Longitude: 138.11111
Latitude: 29.33333
Angle: 30.0
AvgSpeed: 55.5
MsgTime: "2020-12-31 11:11:00"
RouteID: "6"
ProductID: "1"
DualSerialid: "1"
IsArrLeft: "1"
===== gps Byte 开始=====
10321011495750464954564648464918949505546484648464924132340148117708-11354-11467976425-109-5810429858561644900000062645700000-647564661950485048454950455149324949584949584848-1261154-1181149-1101149-1021149
bytes长度107
===== gps Byte 结束 =====
===== 使用gps 反序列化生成对象开始 =====
Header
SrcAddr: "192.168.0.1"
DestAddr: "127.0.0.1"
AckFlag: true
SeqNo: 3
TerminalType: 1
PlatFormType: 1
Longitude: 138.11111
Latitude: 29.33333
Angle: 30.0
AvgSpeed: 55.5
MsgTime: "2020-12-31 11:11:00"
RouteID: "6"
ProductID: "1"
DualSerialid: "1"
IsArrLeft: "1"
===== 使用gps 反序列化生成对象结束 =====
八、总结
使用protobuf可以方便序列化和反序列化对象数据,可以有效防止序列化的过程中因为协议的不一致导致数据解析错误问题。结合消息中间件,可以方便系统间的数据传输。
以上是关于ProtoBuf使用说明的主要内容,如果未能解决你的问题,请参考以下文章