对象序列化(serialization)和反序列化(deserialization)是将对象转化为便于传输的格式进行发送和接收的两个操作。
哪些东西可以是字节?图片可以是字节,文件可以是字节,一个字符串也可以是字节,嗯,宇宙间的一切事物都可以用字节表示。当然,对象也可以是字节。java的序列化就是将对象转化为字节流,以便在进程或网络之间进行传输,而在接收方,需要以相同的方式对字节流进行反序列化,得到传输的对象。
1,实现Serializable接口
package com.java;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
public class Player implements Serializable{
public Player(long playerId, int age, String name) {
this.playerId = playerId;
this.age = age;
this.name = name;
}
private long playerId;
private int age;
private String name;
private List skills = new ArrayList<>();
get() /set()方法
}
2.对象序列化,Java中通过对象流 ObjectOutputStream 进行序列化。
public static byte[] serializable(Object out) throws Exception {
//用于序列化后存储对象
ByteArrayOutputStream byteArrayOutputStream = null;
//java序列化API
ObjectOutputStream objectOutputStream = null;
try {
byteArrayOutputStream = new ByteArrayOutputStream();
objectOutputStream = new ObjectOutputStream(byteArrayOutputStream);
//将out对象进行序列化
objectOutputStream.writeObject(out);
//测试验证输入(获取字节数组)
byte[] bs = byteArrayOutputStream.toByteArray();
//将数组转化为字符串输入
System.out.println(Arrays.toString(bs));
return bs;
} catch (IOException e) {
e.printStackTrace();
}finally {
//关闭最外层的流(内部流会自动关闭)
objectOutputStream.close();
}
return null;
}
3.反序列化为对象,Java中通过对象流 ObjectInputStream 进行序列化。
public static player deserializable(byte[] bs) throws Exception {
//创建存放二进制数据的API
ByteArrayInputStream byteArrayInputStream = null;
//创建反序列化对象
ObjectInputStream objectInputStream = null;
try {
byteArrayInputStream = new ByteArrayInputStream(bs);
objectInputStream = new ObjectInputStream(byteArrayInputStream);
//校验测试
Player player = (Player) objectInputStream.readObject();
System.out.println(player.toString());
} catch (IOException e) {
player = null;
e.printStackTrace();
}finally {
objectInputStream.close();
}
return player;
}
本以为这样就可以了,但使用过程中会有一些问题出现,总结一些遇到的问题吧
测试:
public class TempTest {
public static void main(String[] args) {
CarData date= new CarData();
Object value = new Object("a","123");
system.out.println(Arrays.toString(serializable(value)));
system.out.println(deserialzable(data.getString().getBytes()));
}
4.遇到的问题及解决方式;
(1)打印字符串乱码
其中String和byte[]转换:
String string = "hello world";
//Convert to byte[]
byte[] bytes = string.getBytes();
//Convert back to String
String s = new String(bytes);
输入一些数据测试,出现乱码打印结果:
�� sr java.util.ArrayListx����a� I sizexp w sr com.alibaba.fastjson.JSONObject L mapt Ljava/util/Map;xpsr java.util.HashMap���`� F
loadFactorI thresholdxp?@ t at 123xx
解决方法:
原因:string利用 byte[] bytes = string.getBytes(); String s = new String(bytes);方法和bute[]互转时会出现丢失两字节识别码,所以发生乱码
// 使用Base64解码
System.out.println(deserializable(Base64.getDecoder().decode(value.getstring())));
//value 是一个自定义复杂类型数据,通过getstring()内部方法得到string类型数据
打印结果:
rO0ABXNyABNqYXZhLnV0aWwuQXJyYXlMaXN0eIHSHZnHYZ0DAAFJAARzaXpleHAAAAABdwQAAAABc3IAH2NvbS5hbGliYWJhLmZhc3Rqc29uLkpTT05PYmplY3QAAAAAAAAAAQIAAUwAA21hcHQAD0xqYXZhL3V0aWwvTWFwO3hwc3IAEWphdmEudXRpbC5IYXNoTWFwBQfawcMWYNEDAAJGAApsb2FkRmFjdG9ySQAJdGhyZXNob2xkeHA/QAAAAAAADHcIAAAAEAAAAAF0AAFhdAADMTIzeHg=
[{"a":"123"}]
(2)java.util.Base64报“java.lang.IllegalArgumentException: Illegal base64 character d”的问题
原因:Base64是一种字符串编码格式,采用了A-Z,a-z,0-9,“+”和“/”这64个字符来编码原始字符(还有垫字符“=”)。一个字符本身是一个字节,也就是8位,而base64编码后的一个字符只能表示6位的信息。也就是原始字符串中的3字节的信息编码会变成4字节的信息。Base64的主要作用是满足MIME的传输需求。
在Java8中Base64编码已经成为Java类库的标准,且内置了Base64编码的编码器和解码器。
Base64.getDecoder().decode() 修改为 Base64.getMimeDecoder().decode()
(3)java.io.EOFException报空异常
deSerializable()方法中的将构造ObjectInputStream 对象,放在捕获异常try{}catch{}外面
(4)反序列化过程引发了 java.io.EOFException异常
原因:可能是实现Serializable接口的时候重新实现了tostring()方法,这个格式写的不对,导致异常,最简单的方法就是用Serializable自己的toString()方法.
以上,仅供个人学习记录.