前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >protocol buffer基本科普

protocol buffer基本科普

作者头像
大话swift
修改2019-10-09 15:10:11
7090
修改2019-10-09 15:10:11
举报
文章被收录于专栏:大话swift大话swift大话swift

pb是谷歌退出的序列化数据传输格式,它以多平台支持,高压缩传输更加快速著称

1 为啥支持多平台

pb有一套自己的语法定义数据格式,根据特性的语法形式定义数据,个人可以根据需要自定义DSL进行格式转换各个平台的语言代码,当然了这样的工作量是巨大的,Google为我们提供基于多种语言的转换支持,如

2 为啥能够传输更加快速

对于模型转化的数据pb最终将数据进行了特定的byte编码,相对于xml与json来说将不必要传输的格式定义等数据给去除掉了。通信的两端则通过pb定义出的数据结构转换出的平台代码完成数据编码与解码

3 pb的缺点

pb虽然数据传输量小,但是传输数据不够直观,接收方需要反序列化才可看到数据,在开发中不利于数据的纠错

使用入门

pb是根据.proto文件定义的数据结构进行平台代码转换,一次我们需先创建以文件。在pb数据结构是以message作为一个基本的数据集合体,同时定义出针对平台兼容的数据转换类型表

.proto Type  Notes  C++ Type  Java Type  Python Type[2]  Go Type  Ruby Type  C# Type  PHP Type  Dart Type
double    double  double  float  float64  Float  double  float  double
float    float  float  float  float32  Float  float  float  double
int32  Uses variable-length encoding. Inefficient for encoding negative numbers – if your field is likely to have negative values, use sint32 instead.  int32  int  int  int32  Fixnum or Bignum (as required)  int  integer  int
int64  Uses variable-length encoding. Inefficient for encoding negative numbers – if your field is likely to have negative values, use sint64 instead.  int64  long  int/long[3]  int64  Bignum  long  integer/string[5]  Int64
uint32  Uses variable-length encoding.  uint32  int[1]  int/long[3]  uint32  Fixnum or Bignum (as required)  uint  integer  int
uint64  Uses variable-length encoding.  uint64  long[1]  int/long[3]  uint64  Bignum  ulong  integer/string[5]  Int64
sint32  Uses variable-length encoding. Signed int value. These more efficiently encode negative numbers than regular int32s.  int32  int  int  int32  Fixnum or Bignum (as required)  int  integer  int
sint64  Uses variable-length encoding. Signed int value. These more efficiently encode negative numbers than regular int64s.  int64  long  int/long[3]  int64  Bignum  long  integer/string[5]  Int64
fixed32  Always four bytes. More efficient than uint32 if values are often greater than 228.  uint32  int[1]  int/long[3]  uint32  Fixnum or Bignum (as required)  uint  integer  int
fixed64  Always eight bytes. More efficient than uint64 if values are often greater than 256.  uint64  long[1]  int/long[3]  uint64  Bignum  ulong  integer/string[5]  Int64
sfixed32  Always four bytes.  int32  int  int  int32  Fixnum or Bignum (as required)  int  integer  int
sfixed64  Always eight bytes.  int64  long  int/long[3]  int64  Bignum  long  integer/string[5]  Int64
bool    bool  boolean  bool  bool  TrueClass/FalseClass  bool  boolean  bool
string  A string must always contain UTF-8 encoded or 7-bit ASCII text, and cannot be longer than 232.  string  String  str/unicode[4]  string  String (UTF-8)  string  string  String
bytes  May contain any arbitrary sequence of bytes no longer than 232.  string  ByteString  str  []byte  String (ASCII-8BIT)  ByteString  string

下面我们自定义一个看看看如何

syntax = "proto3";
option java_package = "app.api";

message Menu{
 int32 id = 1;
 string name = 2;
 int32 status = 3;
 int32 parent = 4;
 string link = 5;
}
message MainMenu{
 int32 id = 1;
 string name = 2;
 int32 status = 3;
 int32 parent = 4;
 string link = 5;
 repeated Menu subs = 6;
}

message MenuEntity{
repeated MainMenu menus = 1;
}

上栗中出现了几个关键点

syntax = "proto3";代表的是对应的pb版本

message 类型与struct和class

repeated代表编译出来是个数组或者list

我们看看怎么编译

 protoc --proto_path=./ --java_out=./ *.proto 

proto_path 指定的为pb定义文件的位置

java_out 指代的是编译出的语言此处为java

*.proto 编译那个pb文件,我们此处用的通配符

使用

将编译出的Java代码拷贝项目中即可按照Java方式调用

1 序列化

  mutableListOf<MenuOuterClass.MainMenu.Builder>()
        categories.forEach {
            var mainMenu = MenuOuterClass.MainMenu.newBuilder()
            mainMenu.id = it.id
            mainMenu.name = it.name
            mainMenu.status = it.status
            mainMenu.parent = it.parent
            mainMenu.link = it.link
            it.subs.forEach { menu ->
                var subMenu = MenuOuterClass.Menu.newBuilder()
                subMenu.id = menu.id
                if (!menu.name.isNullOrBlank()) {
                    subMenu.name = menu.name
                }
                subMenu.status = menu.status
                subMenu.parent = menu.parent
                if (!menu.link.isNullOrBlank()) {

                    subMenu.link = menu.link
                }
                mainMenu.addSubs(subMenu)
            }
            menus.addMenus(mainMenu)
        }

Kotlin兼容Java,我们按照Kotlin代码来写

模版类似 MenuOuterClass.Menu.newBuilder()找到对应的build一个个属性赋值即即可,最后使用menus.build().toByteString()转化为byte对应的魔种结构

2数据传输

        response.contentType = "application/x-protobuf"
        menus.build().writeTo(response.outputStream)
        response.flushBuffer()

3 反序列化

通过接收到到流文件进行反序列化(此处我们的是bytestring)

      val decodeEntity =  MenuOuterClass.MenuEntity.parseFrom(byteString)

至此,我们的就可按照对应的class进行业务操作…

公众号了解更多
公众号了解更多
本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-09-26,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 大话swift 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
文件存储
文件存储(Cloud File Storage,CFS)为您提供安全可靠、可扩展的共享文件存储服务。文件存储可与腾讯云服务器、容器服务、批量计算等服务搭配使用,为多个计算节点提供容量和性能可弹性扩展的高性能共享存储。腾讯云文件存储的管理界面简单、易使用,可实现对现有应用的无缝集成;按实际用量付费,为您节约成本,简化 IT 运维工作。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档