文档章节

Google Protobuf编解码(序列化/反序列化)框架

兴趣使然的程序员
 兴趣使然的程序员
发布于 2017/04/05 14:07
字数 997
阅读 323
收藏 0

编码/解码在Java中又称序列化/反序列化,Java本身的序列化反序列化技术生成的二进制码流太大,且转化效率低下,一般不适用于远程跨节点调用的编码框架。

Protobuf全称Protocol Buffers,由谷歌开源而来,特点如下:

  1. 码流小、效率高
  2. 语言平台无关,不只Java可以用,C++、python亦可
  3. 使用数据描述文件,可自动生成代码
  4. 和Facebook Thirft对比,Protobuf并不需要完全在开始就完全定义好全部结构,而可以在后期extends之前的结构,并且仍然可以读取之前结构编码的信息

使用步骤:

  1. 编写.proto类定义文件
  2. 通过提供的编译器产生对应的Java类
  3. 使用提供的API读写信息

1、编写.proto类定义文件

package tutorial;

option java_package = "com.example.tutorial";
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 phones = 4;
}

message AddressBook {
  repeated Person people = 1;
}

文件说明:

  1. package用于区分同名文件,在java_package缺省时,就是产生的bean的包
  2. java_outer_classname指定包含文件中定义的所有类的类,如果缺省,会自动将.proto文件名设为类名
  3. message定义一个类,message中可以包含message
  4. 每个属性后面的 =1、=2等数字是在二进制化数据时,属性的“唯一标识”,在每个message中独立编号

支持的修饰符:

  1. required:标识必须被提供的字段,如果required字段的值没有被提供,编码解码时都会跑出异常;
  2. optional:标识可以提供或不提供的字段,如果不提供,则返回默认值。默认值和java中相似,但是“子message”的字段会全部为空。默认值也可以用[default = value]进行设置;
  3. repeated:标识ArrayList
  4. 每个属性后面的 =1、=2等数字,注意0-15比之后的数字再序列化时少一个字节,固0-15一般用在required和repeated字段上

支持的数据类型:boolint32floatdoublestringenum 

.proto Type Notes C++ Type Java Type Python Type Go Type
double   double double float *float64
float   float float float *float32
int32 虽然可以有负数,但是效率不高 int32 int int *int32
int64 虽然可以有负数,但是效率不高 int64 long int/long[3] *int64
uint32 无符号整数,只能是正数 uint32 int int/long[3] *uint32
uint64 无符号整数,只能是正数 uint64 long int/long[3] *uint64
sint32 有符号整数,表示负数的效率更高 int32 int int *int32
sint64 有符号整数,表示负数的效率更高 int64 long int/long[3] *int64
fixed32 永远占据4个字节,如果超过256的话,效率更高 uint32 int int *uint32
fixed64 永远占据8个字节,如果超过256的话,效率更高 uint64 long int/long[3] *uint64
sfixed32 永远占据4个字节 int32 int int *int32
sfixed64 永远占据8个字节 int64 long int/long[3] *int64
bool   bool boolean bool *bool
string 字符串必须是UTF-8或者7-bit ASCII。 string String str/unicode *string
bytes   string ByteString str []byte

备注:

[3] Python3中不再有int和long之分,而只有不限长度的整型int。

2、通过提供的编译器产生对应的Java类

2.1、将protoc.exe和对应的.proto文件放到项目所在的java文件夹下

protoc.exe --java_out=.\ .\Request.proto

就可以在上面的proto文件中的java_package描述的位置产生指定的文件

3、使用提供的API读写信息

public class TestSubscribeReqProto {
    /**
     * 1、构建对象
     * @return
     */
    public static SubscribeReqProto.SubscribeReq createSubscribeReq(){
        SubscribeReqProto.SubscribeReq.Builder builder =
                SubscribeReqProto.SubscribeReq.newBuilder();
        builder.setSubReqID(1);
        builder.setUserName("caizhijie");
        builder.setProductName("Yellow Book");
        List<String> address = new ArrayList<>();
        address.add("NanJing YuHuaTai");
        address.add("BeiJing ZhiJinCheng");
        address.add("ShenZhen HongShuLin");
        builder.addAllAddress(address);
        return builder.build();
    }

    /**
     * 2、编码
     * @param req
     * @return
     */
    public static byte[] encode(SubscribeReqProto.SubscribeReq req){
        return req.toByteArray();
    }

    /**
     * 3、解码
     * @param body
     * @return
     * @throws InvalidProtocolBufferException
     */
    public static SubscribeReqProto.SubscribeReq decode(byte[] body) throws InvalidProtocolBufferException {
        return SubscribeReqProto.SubscribeReq.parseFrom(body);
    }

    public static void main(String[] args) throws InvalidProtocolBufferException {
        SubscribeReqProto.SubscribeReq req = createSubscribeReq();
        System.out.println("Before encode : "+req.toString());
        SubscribeReqProto.SubscribeReq req2 = decode(encode(req));
        System.out.println("After encode : "+req2.toString());
        System.out.println("Assert equal : -->" + req2.equals(req));
    }
}

 

© 著作权归作者所有

共有 人打赏支持
兴趣使然的程序员
粉丝 23
博文 112
码字总数 87412
作品 0
深圳
程序员
私信 提问
protobuf,json,xml,binary,Thrift之间的对比

golang 使用 protobuf 的教程 golang使用protobuf 一条消息数据,用protobuf序列化后的大小是json的10分之一,xml格式的20分之一,是二进制序列化的10分之一,总体看来ProtoBuf的优势还是很明...

mickelfeng
11/19
0
0
几种序列化协议(protobuf,xstream,jackjson,jdk,hessian)相关数据

别人的相关测试数据: http://code.google.com/p/thrift-protobuf-compare/wiki/Benchmarking 测试纬度 序列化时间 反序列化时间 bytes大小 测试代码 准备protobuf文件 Message.proto文件代码...

SANSOM
2015/08/20
0
0
Google Protobuf——实现跨平台跨语言的序列化/反序列化

Google Protobuf——实现跨平台跨语言的序列化/反序列化 作者:柳大·Poechant 邮箱:zhongchao.ustc#gmail.com (#->@) 博客:Blog.CSDN.net/Poechant 日期:March 15th, 2012 0 Overview G...

晨曦之光
2012/04/24
1K
0
protocol buffers入门基础知识(一)

protocol buffers简介 下载地址 2.protocol buffers优势 3.Protocol Buffers 3.0 技术手册 4.一个pb的demo 执行编译命令生成文件...

Cobbage
10/01
0
0
Spring Cloud OpenFeign集成Protocol Buffer

本文作者张天,著有《Spring Cloud 微服务架构进阶》一书。 背景  在之前的文章中,我们介绍过基于Spring Cloud微服务架构,其中,微服务实例之间的交互方式一般为RESTful HTTP请求或RPC调用...

aoho
10/07
0
0

没有更多内容

加载失败,请刷新页面

加载更多

OSChina 周二乱弹 —— 其实我在地板也睡不着

Osc乱弹歌单(2018)请戳(这里) 【今日歌曲】 @witt-z :分享歌词: 阴天 在不开灯的房间,当所有思绪都一点一点沉淀。 分享莫文蔚的单曲《阴天》: 《阴天》- 莫文蔚 手机党少年们想听歌,...

小小编辑
7分钟前
9
3
微服务分布式事务实现

https://www.processon.com/view/link/5b2144d7e4b001a14d3d2d30

WALK_MAN
今天
3
0
《大漠烟尘》读书笔记及读后感文章3700字

《大漠烟尘》读书笔记及读后感文章3700字: 在这个浮躁的社会里,你有多久没有好好读完一本书了? 我们总觉得自己和别人不一样,所以当看到别人身上的问题时,很少有“反求诸己”,反思自己。...

原创小博客
今天
4
0
大数据教程(9.5)用MR实现sql中的jion逻辑

上一篇博客讲解了使用jar -jar的方式来运行提交MR程序,以及通过修改YarnRunner的源码来实现MR的windows开发环境提交到集群的方式。本篇博主将分享sql中常见的join操作。 一、需求 订单数据表...

em_aaron
今天
3
0
十万个为什么之什么是resultful规范

起源 越来越多的人开始意识到,网站即软件,而且是一种新型的软件。这种"互联网软件"采用客户端/服务器模式,建立在分布式体系上,通过互联网通信,具有高延时(high latency)、高并发等特点...

尾生
今天
3
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部