Protocol Buffer 与 XML、JSON
Protocol Buffer 和 XML、JSON一样都是结构数据序列化的工具,用来实现数据的传递、转换等功能。
- Protocol Buffer序列化之后的结果是二进制流,和XML、JSON不同,不是可以直接理解的字符串内容;
- XML和JSON数据在序列化之后,不需要借助其他工具就可以还原,而Protocol Buffer需要先定义数据格式,即.proto协议;
- 性能方面,Protocol Buffer拥有更优的表现,Protocol Buffer比XML和JSON的体积更小(小3-10倍),序列化和反序列化更快(快20-100倍),使用也简单;
Protocol Buffer序列化与反序列化
- 序列化:按照定义好的.proto协议,将数据转换成二进制流;
- 反序列化:将序列化之后的二进制流转换成对应的数据或对象。
Protocol Buffer基本语法
Protocol Buffer 定义数据格式的文件需要保存在.proto文件中。
其中每一个message代表了一个结构,message中面定义一系列的属性,包括其类型与名称。
.proto文件主要分为三个部分:1、包名部分 2、option部分 3、具体的消息定义
示例代码如下:
package testProtobuf;//生成的数据访问类所在的包名(注意:在此无需写全包路径)
option java_package = "org.zhu.testProtobuf";//生成的数据访问类所在包的全路径
option java_outer_classname = "PersonProbuf";//生成的数据访问类的类名
message Person {
required string name = 1;//必须字段,在后面的使用中必须为该段设置值
required int32 id = 2;//同上
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 PhoneNumber phone = 4;//重复字段(可以认为是一个集合),在后面的使用中可以为该字段设置多个值
}
具体更多语法,参考 developers.google.com/protocol-bu…
简单原理
-
Protocol Buffer将消息里的每个字段 进行编码后,再利用T - L - V 存储方式进行数据的存储,最终得到的是一个二进制字节流;
-
Protocol Buffer对于不同数据类型 采用不同的序列化方式;
-
Protocol Buffer对于数据字段值的独特编码方式与T - L - V数据存储方式,使得 Protocol Buffer序列化后数据量体积很小。
编译.proto文件
即将.proto文件文件转换成Java、C++等多平台的代码。
编译指令如下:
protoc -I=$SRC_DIR --xxx_out=$DST_DIR $SRC_DIR/message_content.proto
其中:
- $SRC_DIR:指定需要编译的.proto文件目录 (如没有提供则使用当前目录)
- xxx_out:xxx根据需要生成代码的类型进行设置,对于Java即java_out
- SRC_DIR相同)
- 最后的路径参数:需要编译的.proto文件的具体路径
这样就可以生成指定语言的pb结构代码了。
对于Android开发来说,需要将.proto文件编译成Java代码,而且最好是能通过Android Studio来实现pb的定义和编译。
Android Studio中编译Protocol Buffer
gradle配置
在根项目的build.gradle文件中:
classpath 'com.google.protobuf:protobuf-gradle-plugin:0.8.8'
在moudle的build.gradle文件中:
apply plugin: 'com.google.protobuf'
android节点下:
sourceSets {
main {
proto {
srcDir 'src/main/proto'
include '**/*.proto'
}
java {
srcDir 'src/main/java'
}
}
}
外层节点:
protobuf {
protoc {
artifact = 'com.google.protobuf:protoc:3.1.0'
}
generateProtoTasks {
all().each { task ->
task.builtins {
remove java
}
task.builtins {
java {}
// Add cpp output without any option.
// DO NOT omit the braces if you want this builtin to be added.
cpp {}
}
}
}
generatedFilesBaseDir = "$projectDir/src/generated"
}
最后在dependencies节点下:
// pb依赖
implementation 'com.google.protobuf:protobuf-java:3.11.0'
implementation 'com.google.protobuf:protoc:3.1.0'
.proto文件编写
与java同级创建一个proto文件夹,在该文件夹下编写.proto文件,编写完成后rebuild项目,就可以获得对应的java文件。