文档章节

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

兴趣使然的程序员
 兴趣使然的程序员
发布于 2017/04/05 14:07
字数 997
阅读 97
收藏 0
点赞 0
评论 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));
    }
}

 

© 著作权归作者所有

共有 人打赏支持
兴趣使然的程序员
粉丝 21
博文 112
码字总数 87412
作品 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
Protobuf 作者不建议在 Deno 中使用 Protobuf

0. 背景 我之前在"如何评价ry(Ryan Dahl)的新项目deno?"的回答中曾经写到: 我比较好奇的是 deno 使用了 Protobuf,而没有使用 Mojo。既然目标是要兼容浏览器,却不使用 Mojo... ... 但是从 ...

justjavac
06/27
0
0
Netty with protobuf(一)

Netty with protobuf 这是一篇关于netty和protobuf2的文章,先来介绍一下protobuf的简单使用。网上有很多基本的protobuf的介绍,这里就不在赘述了。 protobuf官网上提供了一个例子,我们就拿...

秋风醉了
2014/07/26
0
0
采用protobuf降低redis的内存使用

Redis的当前数据存储在内存中,由于内存并不象硬盘一样有着很大的空间,对于服务器来说一般只会提供16G或32G内存。所以让Redis使用这些内存存储更多的数据是比较重要的。在使用redis的sampl...

泥水佬
2013/08/19
0
1
高性能RPC over MINA&google protobuf 代码&实例 (一)

作者的其他文章还不错 ! 原文: http://maoyidao.iteye.com/blog/1636923 最近团队在开发基于移动互联网的项目,又一次涉及到post service,即在服务器集群之间投递消息。是的,又是一个RPC...

干死it
2014/01/25
0
0
比较跨语言通讯框架:Apache Thrift和Google Protobuf

前两天想在微博上发表一个观点:在现在的技术体系中,能用于描述通讯协议的方式很多,xml,json,protobuf,thrift,如果在有如此众多选择的基础上,在设计系统时,还自造协议,自己设计协议类...

摆渡者
2014/07/12
0
0
用 Maven 实现一个 protobuf 的 Java 例子

原文出处:jihite 1. 介绍Protocol Buffers Protocal Buffers(简称protobuf)是谷歌的一项技术,用于结构化的数据序列化、反序列化,常用于RPC 系统(Remote Procedure Call Protocol System...

jihite
05/14
0
0
Google Protocol Buffers 学习笔记

Google Protocol Buffers 学习 Protocol Buffers(PB)是一个用于序列化结构化数据的机制,是谷歌的一个开源项目,在github上有源代码,也有发行版。PB跟XML相似,XML序列化的时候速度是可以...

yejq8
2015/05/17
0
0
开源点评:Protocol Buffers介绍

今天来介绍一下“Protocol Buffers”(以下简称protobuf)这个玩意儿。本来俺在构思“生产者/消费者模式 ”系列的下一个帖子:关于生产者和消费者之间的数据传输格式。由于里面扯到了protobu...

彭苏云
2014/09/26
0
0
Google Protobuf 开发指南

Google Protobuf开发指南 1.简介 l 它是开源项目:http://code.google.com/p/protobuf/ l 由google开发,并且在google内部使用 l Protobuf的作用和xml、json是一回事,但他是二进制格式,性能...

macwe
2013/08/29
0
1

没有更多内容

加载失败,请刷新页面

加载更多

下一页

实现异步有哪些方法

有哪些方法可以实现异步呢? 方式一:java 线程池 示例: @Test public final void test_ThreadPool() throws InterruptedException { ScheduledThreadPoolExecutor scheduledThre......

黄威
今天
0
0
linux服务器修改mtu值优化cpu

一、jumbo frames 相关 1、什么是jumbo frames Jumbo frames 是指比标准Ethernet Frames长的frame,即比1518/1522 bit大的frames,Jumbo frame的大小是每个设备厂商规定的,不属于IEEE标准;...

六库科技
今天
0
0
牛客网刷题

1. 二维数组中的查找(难度:易) 题目描述 在一个二维数组中(每个一维数组的长度相同),每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入...

大不了敲一辈子代码
今天
0
0
linux系统的任务计划、服务管理

linux任务计划cron 在linux下,有时候要在我们不在的时候执行一项命令,或启动一个脚本,可以使用任务计划cron功能。 任务计划要用crontab命令完成 选项: -u 指定某个用户,不加-u表示当前用...

黄昏残影
昨天
0
0
设计模式:单例模式

单例模式的定义是确保某个类在任何情况下都只有一个实例,并且需要提供一个全局的访问点供调用者访问该实例的一种模式。 实现以上模式基于以下必须遵守的两点: 1.构造方法私有化 2.提供一个...

人觉非常君
昨天
0
0
《Linux Perf Master》Edition 0.4 发布

在线阅读:https://riboseyim.gitbook.io/perf 在线阅读:https://www.gitbook.com/book/riboseyim/linux-perf-master/details 百度网盘【pdf、mobi、ePub】:https://pan.baidu.com/s/1C20T......

RiboseYim
昨天
1
0
conda 换源

https://mirrors.tuna.tsinghua.edu.cn/help/anaconda/ conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/free/conda config --add channels https://mir......

阿豪boy
昨天
1
0
Confluence 6 安装补丁类文件

Atlassian 支持或者 Atlassian 缺陷修复小组可能针对有一些关键问题会提供补丁来解决这些问题,但是这些问题还没有放到下一个更新版本中。这些问题将会使用 Class 类文件同时在官方 Jira bug...

honeymose
昨天
0
0
非常实用的IDEA插件之总结

1、Alibaba Java Coding Guidelines 经过247天的持续研发,阿里巴巴于10月14日在杭州云栖大会上,正式发布众所期待的《阿里巴巴Java开发规约》扫描插件!该插件由阿里巴巴P3C项目组研发。P3C...

Gibbons
昨天
1
0
Tomcat介绍,安装jdk,安装tomcat,配置Tomcat监听80端口

Tomcat介绍 Tomcat是Apache软件基金会(Apache Software Foundation)的Jakarta项目中的一个核心项目,由Apache、Sun和其他一些公司及个人共同开发而成。 java程序写的网站用tomcat+jdk来运行...

TaoXu
昨天
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部