Hadoop 的序列化
1. 序列化
1.1 序列化与反序列化的概念
序列化:是指将结构化对象转化成字节流在网上传输或写到磁盘进行永久存储的过程
反序列化:是指将字节流转回结构化对象的逆过程
1.2 序列化的应用
序列化用于分布式数据处理的两大领域
- 进程间通信
- 永久存储
1.3 序列化的格式要求
- 紧凑:体积小,节省带宽
- 快速:序列化过程快速
- 可扩展:新 API 支持旧数据格式
- 支持互操作:跨语言
2. Writable 接口
2.1 说明
Hadoop 使用的序列化格式为 Writeable
Writeable 接口定义了两个方法
- write 将对象写入 DataOutput 二进制流
- readFields 从 DataInput 二进制流读取对象
2.2 Writeable接口实现的类
Writeable 接口实现类包含以下
- int 对应的 Writeable 为 IntWriteable
- Long 对应的 Writeable 为 LongWriteable
- String 对应的 Writeable 为 Text
以 IntWritable 为例,在阅读源码之后发现,可以直接通过 new 的方式直接带参创建实例化对象,也可以调用空参构造创建实例化对象之后通过 set 方法赋值。
2.3 IntWritable 案例
使用 IntWritable 实现 Hadoop 的序列化与反序列化
1 import org.apache.hadoop.io.IntWritable; 2 import org.junit.Test; 3 4 import java.io.*; 5 6 /** 7 * @user: share 8 * @date: 2018/7/28 9 * @description: 测试Hadoop的序列化与反序列化 10 */ 11 public class TestHadoopSerial { 12 13 /** 14 * 单元测试Hadoop的序列化 15 * @throws IOException 16 */ 17 @Test 18 public void testSerial() throws IOException { 19 //创建IntWritable对象 20 IntWritable iw = new IntWritable(66); 21 //创建输出流对象 22 DataOutputStream dos = new DataOutputStream(new FileOutputStream("e:/e/haddop.h")); 23 //iw将值写入输出流dos 24 iw.write(dos); 25 //关闭输出流 26 dos.close(); 27 } 28 29 /** 30 * 单元测试Hadoop的反序列化 31 * @throws IOException 32 */ 33 @Test 34 public void testDeserial() throws IOException { 35 //创建输入流对象 36 DataInputStream dis = new DataInputStream(new FileInputStream("e:/e/haddop.h")); 37 //创建IntWritable对象 38 IntWritable iw = new IntWritable(); 39 //iw读取输入流dis的值 40 iw.readFields(dis); 41 //得到iw中的值 42 int i = iw.get(); 43 //输出i 44 System.out.println(i); 45 //关闭输入流 46 dis.close(); 47 } 48 }
2.4 自定义 PersonWriteable
【自定义 Person 类】
1 import java.io.Serializable; 2 3 /** 4 * @user: share 5 * @date: 2018/7/28 6 * @description: 自定义Person类 7 */ 8 public class Person implements Serializable { 9 10 private String name; 11 private int age; 12 13 public Person() { 14 } 15 16 public Person(String name, int age) { 17 this.name = name; 18 this.age = age; 19 } 20 21 public String getName() { 22 return name; 23 } 24 25 public void setName(String name) { 26 this.name = name; 27 } 28 29 public int getAge() { 30 return age; 31 } 32 33 public void setAge(int age) { 34 this.age = age; 35 } 36 37 @Override 38 public String toString() { 39 return "Person{" + 40 "name='" + name + '\'' + 41 ", age=" + age + 42 '}'; 43 } 44 }
【自定义 PersonWriteable】
1 import org.apache.hadoop.io.Writable; 2 3 import java.io.DataInput; 4 import java.io.DataOutput; 5 import java.io.IOException; 6 7 /** 8 * @user: share 9 * @date: 2018/7/28 10 * @description: 自定义PersonWriteable实现Person的序列化与反序列化 11 */ 12 public class PersonWriteable implements Writable { 13 //定义person 14 private Person person; 15 16 //设置get方法 17 public Person getPerson() { 18 return person; 19 } 20 //设置set方法 21 public void setPerson(Person person) { 22 this.person = person; 23 } 24 25 /** 26 * 重写序列化方法 27 * @param out 28 * @throws IOException 29 */ 30 public void write(DataOutput out) throws IOException { 31 //序列化name字段 32 out.writeUTF(person.getName()); 33 //序列化age字段 34 out.writeInt(person.getAge()); 35 } 36 37 /** 38 * 重写反序列化方法 39 * @param in 40 * @throws IOException 41 */ 42 public void readFields(DataInput in) throws IOException { 43 //初始化person 44 person = new Person(); 45 //反序列化name字段 46 person.setName(in.readUTF()); 47 //反序列化age字段 48 person.setAge(in.readInt()); 49 } 50 }
【Person 的序列化测试类】
1 import org.junit.Test; 2 3 import java.io.*; 4 5 /** 6 * @user: share 7 * @date: 2018/7/28 8 * @description: 测试Person的序列化与反序列化 9 */ 10 public class TestPersonSerial { 11 /** 12 * 单元测试Person的序列化 13 * @throws IOException 14 */ 15 @Test 16 public void testPersonSerial() throws IOException { 17 //新建Person对象 18 Person p = new Person("sam", 20); 19 //创建PersonWriteable对象 20 PersonWriteable pw = new PersonWriteable(); 21 //调用set方法赋值 22 pw.setPerson(p); 23 //创建输出流对象 24 DataOutputStream dos = new DataOutputStream(new FileOutputStream("e:/e/person.j")); 25 //pw将值写入输出流dos 26 pw.write(dos); 27 //关闭输出流 28 dos.close(); 29 } 30 31 /** 32 * 单元测试Person的反序列化 33 * @throws IOException 34 */ 35 @Test 36 public void testPersonDeserial() throws IOException { 37 //创建PersonWriteable对象 38 PersonWriteable pw = new PersonWriteable(); 39 //创建输出流对象 40 DataInputStream dis = new DataInputStream(new FileInputStream("e:/e/person.j")); 41 //读取输入流中的对象 42 pw.readFields(dis); 43 //得到Person对象 44 Person p = pw.getPerson(); 45 //输出Person 46 System.out.println(p.toString()); 47 //关闭输入流 48 dis.close(); 49 } 50 }
且将新火试新茶,诗酒趁年华。