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)和protobuf\src\protoc.exe放在同一个文件夹
3>.编译emp.proto(protoc --java_out=. emp.proto)
4>.将"D:\10.Java\IDE\yhinzhengjieData\ProtocolBuffers\tutorialspoint\com"(这是我本地目录)下的Emp2.java放置在idea中,包名“tutorialspoint.com”
三.编写代码
1>.编写串行化代码
/*
@author :yinzhengjie
Blog:http://www.cnblogs.com/yinzhengjie/tag/Hadoop%E8%BF%9B%E9%98%B6%E4%B9%8B%E8%B7%AF/
EMAIL:y1053419035@qq.com
*/
package cn.org.yinzhengjie.protocolBuffers; import tutorialspoint.com.Emp2; import java.io.File;
import java.io.FileOutputStream; public class MyProtocolBuffers { private static final File protocolBuffers = new File("D:\\10.Java\\IDE\\yhinzhengjieData\\ProtocolBuffers\\emp.protocolBuffers"); public static void main(String[] args) throws Exception {
protocolBuffersSerial();
}
/**
* 定义序列化方式
*/
public static void protocolBuffersSerial() throws Exception {
long start = System.currentTimeMillis();
FileOutputStream fos = new FileOutputStream(protocolBuffers);
//注意,在序列化一个对象的时候,都是打点的方式设置的哟!在设置完毕后需要以".build"结束!
Emp2.Emp emp = Emp2.Emp.newBuilder().
setId(1).
setName("尹正杰").
setAge(18).
setSalary(66666666).
setAddress("北京").build();
//我们循环写入数据
for (int i = 0; i < 10000000; i++) {
emp.writeTo(fos);
}
fos.close();
System.out.printf("这是protocol Buffers序列化方式: 生成文件大小:[%d],用时:[%d]\n",protocolBuffers.length(),System.currentTimeMillis() - start);
}
} /*
以上代码执行结果如下:
这是protocol Buffers序列化方式: 生成文件大小:[280000000],用时:[10960]
*/
执行以上代码后,在本地目录会生成一个文件如下:
2>.编写反串行化代码
/*
@author :yinzhengjie
Blog:http://www.cnblogs.com/yinzhengjie/tag/Hadoop%E8%BF%9B%E9%98%B6%E4%B9%8B%E8%B7%AF/
EMAIL:y1053419035@qq.com
*/
package cn.org.yinzhengjie.protocolBuffers; import tutorialspoint.com.Emp2; import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream; public class MyProtocolBuffers { private static final File protocolBuffers = new File("D:\\BigData\\JavaSE\\yinzhengjieData\\ProtocolBuffers\\emp.protocolBuffers"); public static void main(String[] args) throws Exception {
protocolBuffersSerial();
protocolBuffersDeserial();
}
/**
* 定义序列化方式
*/
public static void protocolBuffersSerial() throws Exception {
long start = System.currentTimeMillis();
FileOutputStream fos = new FileOutputStream(protocolBuffers);
//注意,在序列化一个对象的时候,都是打点的方式设置的哟!在设置完毕后需要以".build"结束!
Emp2.Emp emp = Emp2.Emp.newBuilder().
setId(1).
setName("尹正杰").
setAge(18).
setSalary(66666666).
setAddress("北京").build();
//我们循环写入数据
for (int i = 0; i < 2000000; i++) {
emp.writeTo(fos);
}
fos.close();
System.out.printf("这是protocol Buffers序列化方式: 生成文件大小:[%d],用时:[%d]\n",protocolBuffers.length(),System.currentTimeMillis() - start);
} /**
* 定义反序列化方式
*/
public static void protocolBuffersDeserial() throws Exception {
long start = System.currentTimeMillis();
FileInputStream fis = new FileInputStream(protocolBuffers); Emp2.Emp emp = Emp2.Emp.parseFrom(fis); for (int i = 0; i < 2000000; i++) {
emp.getId();
emp.getName();
emp.getAge();
emp.getSalary();
emp.getAddress();
}
System.out.printf("这是protocol Buffers反序列化方式: 生成文件大小:[%d],用时:[%d]\n",protocolBuffers.length(),System.currentTimeMillis() - start);
} }