参考资料
ProtocolBuffer在Android端的解析
Android Studio使用ProtocolBuffers
在Android中使用Protocol Buffers
Android Protobuf应用及原理-饿了么团队
Protobuf不管在时间和空间上更高效,是怎么做到的呢?
消息经过Protobuf序列化后会成为一个二进制数据流,通过Key-Value组成方式写入到二进制数据流,如图所示:
messge Buffer
安装protobuf-gradle-plugin
protobuf support插件下载编译Protocol编译器
#支持不同语言,Android选择java即可-protobuf-java-3.11.4.zip(需要gcc 和make编译环境)
#后来改为protoc-3.11.4-win64.zip(已经是编译好的,无需再编译)
https://github.com/google/protobuf/releases
进入protobuf目录并执行 autogen.sh--->这个脚本主要用于下载测试用的gmock-1.7.0,并生成用于编译配置的 configure 等文件。
不过我注意到目前下载的已经包括了configure文件
image.png
configure 等文件。可以通过如下命令了解我们可以对protobuf的编译做哪些配置,以及默认配置的信息:
image.png
执行configure对编译进行配置:
configure对编译进行配置 image.png
很可惜的是windows上好像没有对应的make命令,对其进行编译。只好到网络上找一个现成的
#查看版本
protoc3.0.0 --version
#查看帮助
protoc3.0.0 -help
image.png
创建 .proto 文件
.proto 文件中的定义很简单:为每个想要序列化的数据结构添加一个 消息(message) ,然后为消息中的每个字段指定一个名字和类型以及一个tag数字。如官方提供的一个例子addressbook.proto:
addressbook.proto(这里指定了proto的版本,因为proto3.0中已经不支持默认值)
syntax = "proto2";
package protoBuffer;
option java_package = "younghare.com.protoBuffer";
option java_outer_classname = "AddressBookProtos";
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;
}
message AddressBook {
repeated Person person = 1;
}
image.png
编译.proto文件
protoc --java_out=D:/ test.proto Javaout
#后面的是编译输出的路劲地址,第二个參数是须要编译的proto文件
protoc3.0.0 --java_out=D:/ ./addressBook.proto
image.png
生成的位置是--java_out指定的位置加proto中配置的包名
如本例子就是d:\younghare.com.protoBuffer
把生成的代码copy到工程
image.png image.png导入依赖
implementation 'com.google.protobuf:protobuf-lite:3.0.0' //依赖protobuf-lite库 奇怪的是还要类找不到can not resolve symbol com.google.protobuf.ExtensionRegistry
#实在没办法,从其他地方copy protobuf的源码到工程
protobuf的源码copy
编写测试用例
//测试用:系列化与反序列化
@Test
public void testAddressBookWriteFile(){
String pbfilepath = "D:\\temp\\addressBookProtos";
File fproto = new File(pbfilepath);
if (!fproto.exists()) {
try {
fproto.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
}
//构造builder
AddressBookProtos.AddressBook.Builder addressBookBuild = AddressBookProtos.AddressBook.newBuilder();
AddressBookProtos.Person.Builder personBuild = AddressBookProtos.Person.newBuilder();
AddressBookProtos.Person.PhoneNumber.Builder personPhoneNumberBuild = AddressBookProtos.Person.PhoneNumber.newBuilder();
personPhoneNumberBuild.setNumber("138-9999-8888");
personPhoneNumberBuild.setType(AddressBookProtos.Person.PhoneType.HOME);
//填充数据
personBuild.setEmail("young@qq.com");
personBuild.setName("young cai");
personBuild.setId(1);
//addressBookBuild.setPerson(1,personBuild);
//结束 build
AddressBookProtos.Person person = personBuild.build();
//写文件
try {
FileOutputStream foProto = new FileOutputStream(fproto);
person.writeTo(foProto);
foProto.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
//模拟模拟重文件中反序列化回来
byte[] buffer = personBuild.build().toByteArray();
try {
AddressBookProtos.Person person2 = AddressBookProtos.Person.parseFrom(buffer);
System.out.println(person2.getEmail());
} catch (InvalidProtocolBufferException e) {
e.printStackTrace();
}
String strBase64Value = new String(Base64.encodeBase64(buffer));
System.out.println(strBase64Value);
}
允许效果
保存文件 反序列化
网友评论