当前位置: 首页 > article >正文

google protocol buffer全解析------田纪原,2024年安卓开发进阶课程

1.protocol buffer需要定义.proto描述文件,然后通过google提供的编译器生成特定的模型文件,之后就可以作为正常的java对象使用了

2.不可以直接创建对象,需要通过Builder进行

3.只有Builder才可以进行set

4.可以通过对象的toByteArray()和parseFrom()方法进行编码和解码

5.模型文件很大(至少在java这里是如此),其中所有的代码都是定制的,这其实是它很大的缺点之一

接着我们将继续深入探究protobuf的编码原理。

主要分为两个部分

第一部分是之前留下的几个伏笔展示protobuf的使用特性

第二部分是分析protobuf的编码原理,解释特性背后的原因

第一部分,Protobuf使用特性

1.不同类型对象的转换

我们先定义如下一个.proto文件

syntax = “proto3”;

option java_package = “cn.tera.protobuf.model”;
option java_outer_classname = “DifferentModels”;

message Person {
string name = 1;
int32 id = 2;
string email = 3;
}

message Article {
string title = 1;
int32 wordsCount = 2;
string author = 3;
}

其中我们定义了2个模型,一个Person,一个Article,虽然他们的字段名字不相同,但是类型和编号都是一致的

接着我们生成.java文件,最终文件结构如下图

img

此时我们尝试做如下的一个转换

/**

  • 测试不同模型间的转换
  • @throws Exception
    */
    @Test
    public void parseDifferentModelsTest() throws Exception {
    //创建一个Person对象
    DifferentModels.Person person = DifferentModels.Person.newBuilder()
    .setName(“person name”)
    .setId(1)
    .setEmail(“tera@google.com”)
    .build();
    //对person编码
    byte[] personBytes = person.toByteArray();
    //将编码后的数据直接merge成Article对象
    DifferentModels.Article article = DifferentModels.Article.parseFrom(personBytes);
    System.out.println(“article’s title:” + article.getTitle());
    System.out.println(“article’s wordsCount:” + article.getWordsCount());
    System.out.println(“article’s author:” + article.getAuthor());
    }

输出结果如下

article’s title:person name
article’s wordsCount:1
article’s author:tera@google.com

可以看到,虽然jsonBytes是由person对象编码得到的,但是可以用于article对象的解码,不但不会报错,所有的数据内容都是完整保留的

这种兼容性的前提是模型中所定义的字段类型和序号都是一一对应相同的

在平时的编码中,我们经常会遇到从数据库中读取数据模型,然后将其转换成业务模型,而很多时候,这2种模型的内容其实是完全一致的,此时我们也许就可以使用protobuf的这种特性,就可以省去很多低效的赋值代码

2.protobuf序号的重要性

我们看到在定义.proto文件时,字段后面会跟着一个"= X",这里并不是指这个字段的值,而是表示这个字段的“序号”,和正确地编码与解码息息相关,在我看来是protocol buffer的灵魂

我们定义如下的.proto文件,这里注意,Model1和Model2的name和id的序号有不同

syntax = “proto3”;

option java_package = “cn.tera.protobuf.model”;
option java_outer_classname = “TagImportance”;

message Model1 {
string name = 1;
int32 id = 2;
string email = 3;
}

message Model2 {
string name = 2;
int32 id = 1;
string email = 3;
}

定义如下的测试方法

/**

  • 序号的重要性测试
  • @throws Exception
    */
    @Test
    public void tagImportanceTest() throws Exception {
    TagImportance.Model1 model1 = TagImportance.Model1.newBuilder()
    .setEmail(“model1@google.com”)
    .setId(1)
    .setName(“model1”)
    .build();
    TagImportance.Model2 model2 = TagImportance.Model2.parseFrom(model1.toByteArray());
    System.out.println(“model2 email:” + model2.getEmail());
    System.out.println(“model2 id:” + model2.getId());
    System.out.println(“model2 name:” + model2.getName());
    System.out.println(“-------model2 数据---------”);
    System.out.println(model2);
    }

输出结果如下

model2 email:model1@google.com
model2 id:0
model2 name:
-------model2 数据---------
email: “model1@google.com”
1: “model1”
2: 1

可以看到,虽然Model1和Model2定义的字段类型和名字都是相同的,然而name和id的序号颠倒了一下,导致最终model2在解析byte数组时,无法正确将数据解析到对应的字段上,所以输出的id为0,而name字段为null

不过即使字段无法一一对应,但在输出model2.toString()时,我们依然可以看到数据是被解析到了,只不过无法对应到具体字段,只能用1,2来表示其字段名

3.protobuf序号对编码结果大小的影响

protobuf的序号不仅影响编码、解码的正确性,一定程度上还会影响编码结果的字节数

我们在上面的.proto文件中增加一个Model3,其中Model3中定义的字段没有变化,但是序号更改为16,17,18

syntax = “proto3”;

option java_package = “cn.tera.protobuf.model”;
option java_outer_classname = “TagImportance”;

message Model1 {
string name = 1;
int32 id = 2;
string email = 3;
}

message Model2 {
string name = 2;
int32 id = 1;
string email = 3;
}

message

http://www.lryc.cn/news/2417193.html

相关文章:

  • js中的offsetLeft和style.left
  • 计算机丢失msvcrtdll怎么修复,雨林木风修复msvcrtdll 【操作方案】 的详细_
  • 人工智能与物流:智能化的物流管理
  • rearm 命令_运行输入slmgr.vbs -rearm 命令什么意思
  • 电脑蓝屏代码大全合集
  • nii文件中的方向理解
  • LLT与HLT测试简介
  • Linux内核:Pci设备驱动——设备枚举
  • 老挑毛u盘一键装系统计算机意外地,揭谜一键Ghost的“恶”事 大白菜、老毛桃、通用都不干净...
  • order by、sort by、distribute by sort by 、cluster by、group by order by、partition by order by 解析
  • 4转换vsn格式_文件格式转换麻烦?教你一招,PDF、Word、PPT随便转
  • 抓取sankakucomplex图片
  • DNS(Bind9) Anycast 数据中心部署 最终版
  • Linux淘金记(一):module_init——初始化就该这么写
  • IOS-Moya简单使用-Swift
  • Myo肌电臂环中文入门指南及基于matlab获取Myo臂环信号
  • C++11重写muduo网络库——预备知识
  • 行业分析
  • 为什么有时候启动Activity需要加FLAG_ACTIVITY_NEW_TASK
  • 制作一个简单HTML中华传统文化网页设计源码(HTML+CSS)
  • GRUB4DOS使用大全
  • 《Head first Java》练习
  • asdasdasdasdasdas
  • 位图(bmp)文件格式分析
  • CPU架构名词解释
  • 计算机网络之网络基础网络通信原理(非常重要的网络基础知识,内含思维导图和详细图解)
  • 药娘化女仆公读《乡村振兴战略下传统村落文化旅游设计》晏嘤茹苦辉少许
  • 大家厚爱
  • maven冲突解决-enforcer插件介绍
  • 数学规划模型之线性规划