Google Protobuf编解码(序列化/反序列化)框架
2017-04-05 00:00
169 查看
编码/解码在Java中又称序列化/反序列化,Java本身的序列化反序列化技术生成的二进制码流太大,且转化效率低下,一般不适用于远程跨节点调用的编码框架。
Protobuf全称Protocol Buffers,由谷歌开源而来,特点如下:
码流小、效率高
语言平台无关,不只Java可以用,C++、python亦可
使用数据描述文件,可自动生成代码
和Facebook Thirft对比,Protobuf并不需要完全在开始就完全定义好全部结构,而可以在后期extends之前的结构,并且仍然可以读取之前结构编码的信息
使用步骤:
编写.proto类定义文件
通过提供的编译器产生对应的Java类
使用提供的API读写信息
java_outer_classname指定包含文件中定义的所有类的类,如果缺省,会自动将.proto文件名设为类名
message定义一个类,message中可以包含message
每个属性后面的 =1、=2等数字是在二进制化数据时,属性的“唯一标识”,在每个message中独立编号
optional:标识可以提供或不提供的字段,如果不提供,则返回默认值。默认值和java中相似,但是“子message”的字段会全部为空。默认值也可以用[default = value]进行设置;
repeated:标识ArrayList
每个属性后面的 =1、=2等数字,注意0-15比之后的数字再序列化时少一个字节,固0-15一般用在required和repeated字段上
支持的数据类型:
备注:
[3] Python3中不再有int和long之分,而只有不限长度的整型int。
就可以在上面的proto文件中的java_package描述的位置产生指定的文件
Protobuf全称Protocol Buffers,由谷歌开源而来,特点如下:
码流小、效率高
语言平台无关,不只Java可以用,C++、python亦可
使用数据描述文件,可自动生成代码
和Facebook Thirft对比,Protobuf并不需要完全在开始就完全定义好全部结构,而可以在后期extends之前的结构,并且仍然可以读取之前结构编码的信息
使用步骤:
编写.proto类定义文件
通过提供的编译器产生对应的Java类
使用提供的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; }
文件说明:
package用于区分同名文件,在java_package缺省时,就是产生的bean的包java_outer_classname指定包含文件中定义的所有类的类,如果缺省,会自动将.proto文件名设为类名
message定义一个类,message中可以包含message
每个属性后面的 =1、=2等数字是在二进制化数据时,属性的“唯一标识”,在每个message中独立编号
支持的修饰符:
required:标识必须被提供的字段,如果required字段的值没有被提供,编码解码时都会跑出异常;optional:标识可以提供或不提供的字段,如果不提供,则返回默认值。默认值和java中相似,但是“子message”的字段会全部为空。默认值也可以用[default = value]进行设置;
repeated:标识ArrayList
每个属性后面的 =1、=2等数字,注意0-15比之后的数字再序列化时少一个字节,固0-15一般用在required和repeated字段上
支持的数据类型:bool
, int32
, float
, double,
string
, enum
.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)); } }
相关文章推荐
- java 常用序列化和反序列化框架使用-json,kyro,jdk
- 分布式服务框架学习笔记3 序列化、反序列化与协议栈
- java 常用序列化和反序列化框架使用demo
- 20161025:今日大数据知识总结(zookeeper回顾+序列化反序列化回顾+avro+zebro项目框架的搭建)
- 使用zmq,probuf,缓冲池实现序列化和反序列化框架(一)-使用ConcurrentLinkedQueue实现缓冲池
- 使用zmq,probuf,缓冲池实现序列化和反序列化框架(二)-ZMQ介绍
- XML和实体类之间相互转换(序列化和反序列化)
- java序列化和反序列化
- JAVA中序列化和反序列化
- C#中Json序列化、反序列化
- Java对象的序列化和反序列化实践
- 对象的序列化和反序列化实践
- Java对象的序列化和反序列化实践
- LIST<T>现在也支持序列化和反序列化了
- 再弄一片文章凑个4篇文章的数,主要是用于XML和 Binary序列化和反序列化的类
- 对象序列化及反序列化帮助类
- 如何自定义序列化和反序列化
- 使用Protostuff序列化及反序列化优化调试
- Android轻量级JSON序列化和反序列化
- 297. Serialize and Deserialize Binary Tree 序列化及反序列化