java中序列化与反序列化

本文详细介绍了Java中使用ObjectInputStream与ObjectOutputStream进行对象序列化与反序列化的原理、过程及注意事项,包括如何实现Serializable接口、序列化时忽略属性的方法、以及序列化与反序列化的基本操作步骤。

(一)  InputStreamReader和OutputStreamWriter:

1.        将字节流(8位)转换成字符流(16位)可以使用InputStreamReader和OutputStreamWriter来进行读和写。

2.        InputStreamReaderOutputStreamWriter是字节流通向字符流的桥梁

(二)  DataInputStream和DataOutputStream读写Java基本类型(int,double…..)的数据。不可以读写复杂的引用类型实例,如Employee,Book….。

 

(三)   ObjectInputStream与ObjectOutputStream能够使内存中的对象保存到文件里或从文件里读回原来的对象,即完成对象的序列化与反序列化(将内存中的对象永久保存在媒介上)。

JVM: Employees e1, e2,e3 ----序列化----> emp.bin

文件:Emp.bin ----反序列化----> e1,e2,e3对象

 

1.        所有需要被序列化对象的类必须要实现java.io.Serializable(我们把这种接口称为标识接口)接口。Serializable接口中没有方法我们将这种特殊的接口叫做标识接口(标识一种可序列化的类型)。

如:

public class Employee implementsjava.io.Serializable {

    ......

}

2.        在序列化时需要忽略的属性可以用transient关键字修饰。

3.        被序列化对象的属性要求也要能被序列化。


例子:

下面是2个测试类,一个员工类。首先是将一个员工类利用构造函数初始化,把其中的信息通过序列化存入一个指定的文件,然后通过反序列化读入JVM内存,进行控制台输出。

首先是Employee,必须实现Serializable接口:

/**
 * java.io.Serializable接口中没有声明任何方法,我们把这种接口称为标识接口,
 * 标识一个对象只要实现了这个接口,它才能被写入到文件。并且还要求类中的属性也是能被序列化的。
 *
 */
public class Employee implements Serializable{
	
	private Integer empno;
	
	//transient表示临时的性的,这个关键字定义的属性在序列化过程中会被忽略。
	private transient String password; // 敏感数据

	private String ename;
	private Double sal;

	public Employee() {
		super();
	}

	public Employee(Integer empno, String password, String ename, Double sal) {
		super();
		this.empno = empno;
		this.password = password;
		this.ename = ename;
		this.sal = sal;
	}

	public Integer getEmpno() {
		return empno;
	}

	public void setEmpno(Integer empno) {
		this.empno = empno;
	}

	public String getPassword() {
		return password;
	}

	public void setPassword(String password) {
		this.password = password;
	}

	public String getEname() {
		return ename;
	}

	public void setEname(String ename) {
		this.ename = ename;
	}

	public Double getSal() {
		return sal;
	}

	public void setSal(Double sal) {
		this.sal = sal;
	}

	@Override
	public String toString() {
		return "Employee [empno=" + empno + ", password=" + password
				+ ", ename=" + ename + ", sal=" + sal + "]";
	}

}

然后是序列化实现类:

public static void main(String[] args) {
		ObjectOutputStream oos = null;
		
		try {
			oos = new ObjectOutputStream(new FileOutputStream("emp.bin"));
			//对象要能被序列化就必须实现java.io.Serializable接口
			Employee e1 = new Employee(1000, "abcd", "小花", 4000.0);
			Employee e2 = new Employee(1002, "1234", "小燕", 4900.0);
			Employee e3 = new Employee(1003, "xxxx", "小丽", 4500.0);
			Employee e4 = new Employee(1004, "yyyy", "小刘", 5000.0);
			
			System.out.println(e1);
			
			oos.writeObject(e1);
			oos.writeObject(e2);
			oos.writeObject(e3);
			oos.writeObject(e4);
			
			oos.writeObject(null);//作为结束标记
			
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}finally{
			try {
				oos.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		
		

	}

最后是反序列化:

public static void main(String[] args) {
		// 反序列化(即将存在文件中的对象状态还原的JVM内存)
		ObjectInputStream ois = null;
		
		try {
			ois = new ObjectInputStream(new FileInputStream("emp.bin"));
			Object obj = null;
			while ((obj = ois.readObject()) != null) {
				Employee emp = (Employee)obj;
				System.out.println(emp);
			}
			//对象读完出来后报了一个:java.io.EOFException, 已读到文件结束位置了还继续读,就会出这个异常。
			
			
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}finally{
			try {
				ois.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}

	}

最后可以看到Employee类中的password前面加了transient而没有被写入文件,因此也不会被读出来了。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值