Hadoop基础-Protocol Buffers串行化与反串行化
作者:尹正杰
版权声明:原创作品,谢绝转载!否则将追究法律责任。
我们之前学习过很多种序列化文件格式,比如python中的pickle序列化方式(https://www.cnblogs.com/yinzhengjie/p/8531308.html),golang的Gob序列化方式(https://www.cnblogs.com/yinzhengjie/p/7807051.html),hadoop的SequenceFile序列化文件(https://www.cnblogs.com/yinzhengjie/p/9114301.html),Java内置的ObjectOutputStream序列化方式(https://www.cnblogs.com/yinzhengjie/p/8988003.html)等等。
当然,除了语言自己内置的序列化方式外,还有一些手动二进制编码的序列化文件,以及人性化可读格式的序列化文件,比如XMl,JSON,DOM,SAX,STAX,JAXB,JAXP等等,不过这些序列化方式都不是今天的主角,我今天要介绍的是Google公司在2008年就开源的一种序列化方式,即Protocol Buffers序列化。
一.Protocol Buffers 简介
1>.什么是 Protocol Buffers
第一:A description language(一种描述语言);
第二:A complier(它是一个编译器);
第三:A library(它是一种库);
2>.Protocol Buffers 优点
第一:易于使用,高效的二进制编码;
第二:它是由谷歌公司研发的;
第三:简单高效的串行化技术,在2008公开该技术;
3>.支持跨语言
官方支持:Java, C++, and Python等等
非官方支持:C, C#, Erlang, Perl, PHP, Ruby等等
二.Protocol Buffers 代码生成
1>.创建emp.proto自描述文件(非java文件,具体内容如下)
package tutorial; option java_package = "tutorialspoint.com"; option java_outer_classname = "Emp2"; message Emp { required int32 id = 1; required string name = 2; required int32 age = 3; required int32 salary = 4; required string address = 5; }
2>.将emp.proto(下载地址:链接:https://pan.baidu.com/s/1crYmFwI68kUnzwJgoyOdpw 密码:bh63)和protobufsrcprotoc.exe放在同一个文件夹
3>.编译emp.proto(protoc --java_out=. emp.proto)
4>.将"D:10.JavaIDEyhinzhengjieDataProtocolBuffers utorialspointcom"(这是我本地目录)下的Emp2.java放置在idea中,包名“tutorialspoint.com”
三.编写代码
1>.编写串行化代码
1 /* 2 @author :yinzhengjie 3 Blog:http://www.cnblogs.com/yinzhengjie/tag/Hadoop%E8%BF%9B%E9%98%B6%E4%B9%8B%E8%B7%AF/ 4 EMAIL:y1053419035@qq.com 5 */ 6 package cn.org.yinzhengjie.protocolBuffers; 7 8 import tutorialspoint.com.Emp2; 9 10 import java.io.File; 11 import java.io.FileOutputStream; 12 13 public class MyProtocolBuffers { 14 15 private static final File protocolBuffers = new File("D:\10.Java\IDE\yhinzhengjieData\ProtocolBuffers\emp.protocolBuffers"); 16 17 18 public static void main(String[] args) throws Exception { 19 protocolBuffersSerial(); 20 } 21 /** 22 * 定义序列化方式 23 */ 24 public static void protocolBuffersSerial() throws Exception { 25 long start = System.currentTimeMillis(); 26 FileOutputStream fos = new FileOutputStream(protocolBuffers); 27 //注意,在序列化一个对象的时候,都是打点的方式设置的哟!在设置完毕后需要以".build"结束! 28 Emp2.Emp emp = Emp2.Emp.newBuilder(). 29 setId(1). 30 setName("尹正杰"). 31 setAge(18). 32 setSalary(66666666). 33 setAddress("北京").build(); 34 //我们循环写入数据 35 for (int i = 0; i < 10000000; i++) { 36 emp.writeTo(fos); 37 } 38 fos.close(); 39 System.out.printf("这是protocol Buffers序列化方式: 生成文件大小:[%d],用时:[%d] ",protocolBuffers.length(),System.currentTimeMillis() - start); 40 } 41 } 42 43 /* 44 以上代码执行结果如下: 45 这是protocol Buffers序列化方式: 生成文件大小:[280000000],用时:[10960] 46 */
执行以上代码后,在本地目录会生成一个文件如下:
2>.编写反串行化代码
1 /* 2 @author :yinzhengjie 3 Blog:http://www.cnblogs.com/yinzhengjie/tag/Hadoop%E8%BF%9B%E9%98%B6%E4%B9%8B%E8%B7%AF/ 4 EMAIL:y1053419035@qq.com 5 */ 6 package cn.org.yinzhengjie.protocolBuffers; 7 8 import tutorialspoint.com.Emp2; 9 10 import java.io.File; 11 import java.io.FileInputStream; 12 import java.io.FileOutputStream; 13 14 public class MyProtocolBuffers { 15 16 private static final File protocolBuffers = new File("D:\BigData\JavaSE\yinzhengjieData\ProtocolBuffers\emp.protocolBuffers"); 17 18 19 public static void main(String[] args) throws Exception { 20 protocolBuffersSerial(); 21 protocolBuffersDeserial(); 22 } 23 /** 24 * 定义序列化方式 25 */ 26 public static void protocolBuffersSerial() throws Exception { 27 long start = System.currentTimeMillis(); 28 FileOutputStream fos = new FileOutputStream(protocolBuffers); 29 //注意,在序列化一个对象的时候,都是打点的方式设置的哟!在设置完毕后需要以".build"结束! 30 Emp2.Emp emp = Emp2.Emp.newBuilder(). 31 setId(1). 32 setName("尹正杰"). 33 setAge(18). 34 setSalary(66666666). 35 setAddress("北京").build(); 36 //我们循环写入数据 37 for (int i = 0; i < 2000000; i++) { 38 emp.writeTo(fos); 39 } 40 fos.close(); 41 System.out.printf("这是protocol Buffers序列化方式: 生成文件大小:[%d],用时:[%d] ",protocolBuffers.length(),System.currentTimeMillis() - start); 42 } 43 44 /** 45 * 定义反序列化方式 46 */ 47 public static void protocolBuffersDeserial() throws Exception { 48 long start = System.currentTimeMillis(); 49 FileInputStream fis = new FileInputStream(protocolBuffers); 50 51 Emp2.Emp emp = Emp2.Emp.parseFrom(fis); 52 53 for (int i = 0; i < 2000000; i++) { 54 emp.getId(); 55 emp.getName(); 56 emp.getAge(); 57 emp.getSalary(); 58 emp.getAddress(); 59 } 60 System.out.printf("这是protocol Buffers反序列化方式: 生成文件大小:[%d],用时:[%d] ",protocolBuffers.length(),System.currentTimeMillis() - start); 61 } 62 63 }