多应用+插件架构,代码干净,二开方便,首家独创一键云编译技术,文档视频完善,免费商用码云13.8K 广告
## 一、概述 类似 Json或 xml,ProtoBuf是一种数据交换协议;跟json和xml这类相比,其在效率、兼容性等方面非常出色; ### **特点:** * **语言无关、平台无关**。即 ProtoBuf 支持 Java、C++、Python 等多种语言,支持多个平台; * **高效**。即比 xml更小(3 ~ 10倍)、更快(20 ~ 100倍)、更为简单; * **扩展性、兼容性好**。你可以更新数据结构,而不影响和破坏原有的旧程序; ### **比较** * xml、Json、ProtoBuf 都具有**数据结构化**和**数据序列化**的能力 * xml、Json更注重**数据结构化**,关注人类可读性和语义表达能力。ProtoBuf 更注重**数据序列化**,关注效率、空间、速度,人类可读性差,语义表达能力不足(为保证极致的效率,会舍弃一部分元信息) * ProtoBuf 的应用场景更为明确,xml、Json的应用场景更为丰富。 ## 二、使用 **第一步,创建 .proto 文件,定义数据结构,如下所示** ~~~protobuf syntax = "proto3"; option java_package = "com.ray.test.protos"; option java_outer_classname = "RayProtoModel"; message Model { int64 id = 1; string action = 2; string content = 3; string sender = 4; string receiver = 5; string extra = 6; string title = 7; string format = 8; int64 timestamp = 9; } ~~~ 字段定义规则: ~~~protobuf message xxx { // 字段规则:required -> 字段只能也必须出现 1 次 // 字段规则:optional -> 字段可出现 0 次或1次 // 字段规则:repeated -> 字段可出现任意多次(包括 0) // 类型:int32、int64、sint32、sint64、string、32-bit .... // 字段编号:0 ~ 536870911(除去 19000 到 19999 之间的数字) 字段规则 类型 名称 = 字段编号; } ~~~ **第二步,protoc 编译 .proto 文件生成读写接口** 我们在 .proto 文件中定义了数据结构,这些数据结构是面向开发者和业务程序的,并不面向存储和传输; 当需要把这些数据进行存储或传输时,就需要将这些结构数据进行序列化、反序列化以及读写。那么如何实现呢?不用担心, ProtoBuf 将会为我们提供相应的接口代码。如何提供?答案就是通过 protoc 这个编译器; ### **下载安装** 下载编译器:[Releases · protocolbuffers/protobuf (github.com)](https://github.com/protocolbuffers/protobuf/releases),取最新版本,找到类似如下包下载: ![](https://img.kancloud.cn/27/52/2752b31121ae71c3931bdd3e3c92c830_1366x657.png) 解压文件包: ![](https://img.kancloud.cn/ea/fb/eafb314bd739d4424be1e7bea88632b1_948x301.png) bin目录中,包含了protoc编译器; ![](https://img.kancloud.cn/69/e4/69e4438e2e5421161ec3bc7fe794e2bd_913x295.png) ### **生成代码** 可通过如下命令生成相应的接口代码,以java为例: ~~~ protoc.exe -I=${protofilepath}--java_out=${javaout} ${protofilepathwithfilename} ~~~ ![](https://img.kancloud.cn/98/91/98915ed4aaba409674af2bd35282339e_677x457.png) 生成的代码: ![](https://img.kancloud.cn/8e/07/8e07056268156a94f6901e7544c14129_1086x429.png) **第三步,调用接口实现序列化、反序列化以及读写** ``` public class ProtoBufUtil { public static void main(String[] args) throws IOException { RayProtoModel.Model.Builder builder = RayProtoModel.Model.newBuilder(); builder.setId(1); builder.setAction("2"); builder.setExtra("3"); RayProtoModel.Model model = builder.build(); System.out.println(model.toString()); // 模拟将对象转成byte[],方便传输 for (byte b : model.toByteArray()) { System.out.print(b); } System.out.println(model.toByteString()); // 模拟接收Byte[],反序列化成Model类 byte[] byteArray = model.toByteArray(); RayProtoModel.Model p2 = RayProtoModel.Model.parseFrom(byteArray); System.out.println("after :" + p2.toString()); } } ```