java序列化和反序列化以及遇到的问题和解决方法

对象序列化(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<Integer> 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()方法.

 

以上,仅供个人学习记录.

 
  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值