什么是Java序列化,如何实现序列化
1 序列化概念
- 序列化就是一个把Java对象编码成一串二进制的过程
- 序列化的用途:可以将对象放入文件存储、或者放入网络传输
- 反序列化就是一个解码的过程
- 序列化没有固定的标准,有各种各样序列化的方法
Java自带序列化接口
- 创建一个User类
- 在main方法里创建User对象,通过ObjectOutputStream把对象写入到文件中
- 编译报错
- 因为该对象不能被序列化
- 让User类实现 Serializable 接口
- 把User对象写入到文件成功!
- 我们发现写入后的文件大小比对象所有的属性值大很多
- 因为java的Serializable会把类的继承体系也写到文件里,多了很多额外的信息
- 会变得更臃肿,不利于大数据的数据在分布式系统中传输
[Java] 纯文本查看 复制代码1234567private
static
void
encoding()
throws
Exception {
ObjectOutputStream os =
new
ObjectOutputStream(
new
FileOutputStream(
"E:/test/obj1.txt"
));
SerializableUser user =
new
SerializableUser();
user.set(
"9521"
,
"周星星"
,
23
, 10000D);
os.writeObject(user);
os.close();
}
-
[Java] 纯文本查看 复制代码1234567
private
static
void
decoding()
throws
Exception {
ObjectInputStream oi =
new
ObjectInputStream(
new
FileInputStream(
"E:/test/obj1.txt"
));
Object object = oi.readObject();
SerializableUser user = (SerializableUser) object;
System.out.println(user);
oi.close();
}
自定义序列化(FileOutputStream)
- 我们通过把对象的属性拼接成字符串
- 通过 FileOutputStream 将字符串写入文件中
- 写入后发现文件大小变小了很多(由150字节 --> 50字节)
- 因为所有的属性都变成字符串格式,没有额外的信息
- 反序列化的时候读取一行数据自己切割后放入对象
- 存在一个问题,如果是一个Int类型的值,它变成字符串后字节长度变长了
将对象转成 json 格式再序列化
- 通过把对象转成 json 格式序列化后可以很方便的对数据进行操作
[Java] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
|
private static void encoding2() throws Exception { SerializableUser user = new SerializableUser(); user.set( "9521" , "周星星" , 23 , 10000D); Gson gson = new Gson(); String json = gson.toJson(user); System.out.println(json); FileOutputStream fos = new FileOutputStream( "E:/test/obj2.txt" ); fos.write(json.getBytes( "utf-8" )); fos.flush(); fos.close(); } |
[Java] 纯文本查看 复制代码
1
2
3
4
5
6
7
8
|
private static void decoding2() throws Exception { BufferedReader br = new BufferedReader( new InputStreamReader(( new FileInputStream( "E:/test/obj2.txt" )))); String json = br.readLine(); br.close(); Gson gson = new Gson(); SerializableUser user = gson.fromJson(json, SerializableUser. class ); System.out.println(user); } |
通过 DataOutputStream 优化上述代码
- 将对象中的每一个属性按照它原来的类型进行逐个编码
- 可以对基本数据类型按类型机制编解码
- 我们通过 DataOutputStream 把属性一个一个写入到文件
- 发现通过这种方式序列化后文件更加小了(再由50字节 --> 29字节)
- 字符串在原来长度上多2个字符,用于表示字符串的边界
[Java] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
|
private static void encoding3() throws Exception { SerializableUser user = new SerializableUser(); user.set( "9521" , "周星星" , 23 , 10000D); DataOutputStream dos = new DataOutputStream( new FileOutputStream( "E:/test/obj3.txt" )); dos.writeUTF(user.getId()); dos.writeUTF(user.getName()); dos.writeInt(user.getAge()); dos.writeDouble(user.getSalary()); dos.flush(); dos.close(); } |
[Java] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
|
private static void decoding3() throws Exception { SerializableUser user = new SerializableUser(); DataInputStream dis = new DataInputStream( new FileInputStream( "E:/test/obj3.txt" )); String id = dis.readUTF(); String name = dis.readUTF(); int age = dis.readInt(); double salary = dis.readDouble(); user.set(id, name, age, salary); System.out.println(user); dis.close(); } |
总结
- Hadoop内部也有一套自己的序列化框架:提供了一个接口Writable
- 我们的类只要实现了Writable接口,hadoop内部就能用自己的序列化机制去序列化这个类的对象
- 更多学习资料可关注:annalin1203获取