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

@Testpublic 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");//dataBusArrLeftMsg 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.11111Latitude: 29.33333Angle: 30.0AvgSpeed: 55.5MsgTime: "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-1021149bytes长度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.11111Latitude: 29.33333Angle: 30.0AvgSpeed: 55.5MsgTime: "2020-12-31 11:11:00"RouteID: "6"ProductID: "1"DualSerialid: "1"IsArrLeft: "1"===== 使用gps 反序列化生成对象结束 =====

八、总结

使用protobuf可以方便序列化和反序列化对象数据,可以有效防止序列化的过程中因为协议的不一致导致数据解析错误问题。结合消息中间件,可以方便系统间的数据传输。

来源:https://www.icode9.com/content-4-810101.html

(0)

相关推荐