赞
踩
1、介绍:
protocol buffer(简称protobuf),是谷歌出品的序列化框架,与开发语言无关,与平台无关,具有良好的可扩展性。可用于数据存储、通信协议等。
protobuf生成的语言包括很多中:Java、C++、Go、C#等等,通过命令可以使proto文件生成对应的文件。
protobuf的优缺点:
- 性能好、效率高
- 代码生成机制
- 支持向前兼容和向后兼容
- 支持多种编程语言
缺点:
- 应用不够广泛
- 二进制文件可读性差
- 缺乏自描述
2、序列化和反序列化:
Java序列化是指将对象转换为字节序列的过程,反序列化是将字节序列恢复成对象的过程。
序列化分为两大部分:序列化和反序列化。序列化是这个过程的第一部分,将数据分解成字节流,以便存储在文件中或在网络上传输。反序列化就是打开字节流并重构对象。对象序列化不仅要将基本数据类型转换成字节表示,有时还要恢复数据。恢复数据要求有恢复数据的对象实例。
为什么需要序列化与反序列化
我们知道,当两个进程进行远程通信时,可以相互发送各种类型的数据,包括文本、图片、音频、视频等, 而这些数据都会以二进制序列的形式在网络上传送。那么当两个Java进程进行通信时,能否实现进程间的对象传送呢?答案是可以的。如何做到呢?这就需要Java序列化与反序列化了。换句话说,一方面,发送方需要把这个Java对象转换为字节序列,然后在网络上传送;另一方面,接收方需要从字节序列中恢复出Java对象。
而Java序列化的协议主要XML、JSON格式,还有Protobuf。
Protobuf序列化的结果体积要比XML和JSON的小很多。XML和JSON的描述信息太多了,导致消息要大;此外Portobuf还使用了Varint 编码,减少数据对空间的占用。
在速度方面,Protobuf也比XML和JSON快很多,是直接把对象和字节数组做转换。
3、快速开始:
Windows下安装:
下载地址:Protobuf编译器下载
注意选择protoc-3.1.0-win32.zip。
下载完毕后,将其解压到磁盘英文路径下,例如d:/protobuf,里面有bin和include两个目录。
配置环境变量,点击【计算机】-【属性】-【高级系统设置】-【环境变量】,找到并编辑PATH,在尾巴上增加d:/protobuf/bin;。
验证,打开cmd窗口,输入protoc --version,会看到版本信息:libprotoc 3.1.0。否则就是环境变量没有配置正确。
MacOs下:
1.1 安装brew
ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
1.2 使用brew安装protobuf
brew install protobuf
1.3 查看protoc版本
~$ protoc --version
4、编写Proto文件:
4.1编写文件:
我们需要编写proto文件,定义程序中需要处理的结构化数据,在protobuf中,结构化数据被称为 Message。proto 文件非常类似java的pojo bean。我们创建了一个名为Head.proto的文件(txt文本),并在文件里描述了Head数据结构,一共有两个属性,分别是length和magic_number。这里我们使用的protobuf语法是proto3,需要在第一行声明;否则,默认使用proto2。
proto文件对应序列化理论中的IDL(Interface description language,接口描述语言)。
Head.proto:
syntax="proto3";
option java_package = "com.immomo.CopyDemo";
option java_outer_classname = "HeadProtibuf";
message Head {
int32 magic_number = 1;
int32 length = 2;
}
4.2:编译:
使用命令将自动编译出一个HeadProtibuf类:
protoc --java_out=./ Head.proto
4.3 调用代码:
package org.serialization.protobuf.quickstart; import com.google.protobuf.InvalidProtocolBufferException; /** * 演示了使用Protobuf序列化和反序列化Head对象。 */ public class Main { public static void main(String[] args) { // 序列化 //将序列化后二进制数据写入到指定文件中 FileOutputStream fos = new FileOutputStream("/Users/data.txt"); // 创建Head的Builder HeadProtobuf.Head.Builder HeadBuilder = HeadProtobuf.Head.newBuilder(); // 设置Head的属性 HeadBuilder.setMagic_number(18); HeadBuilder.setLength(20); // 创建Head HeadProtobuf.Head head = HeadBuilder.build(); // 序列化,byte[]可以被写到磁盘文件,或者通过网络发送出去。 byte[] data = head.toByteArray(); //序列化到指定的文件中 fos.writeTo(fos); System.out.println("serialization end."); // 反序列化,byte[]可以读文件或者读取网络数据构建。 FileInputStream fis = new FileInputStream("/Users/data.txt"); System.out.println("deserialization begin."); try { HeadProtobuf.Head head1 = HeadProtobuf.Head.parseFrom(fis); HeadProtobuf.Head head2 = HeadProtobuf.Head.parseFrom(data); System.out.println(head1.getMagic_number()); System.out.println(person.getLength()); } catch (InvalidProtocolBufferException e) { e.printStackTrace(); } } }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。