欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Java中对象的序列化和反序列化操作

程序员文章站 2022-06-11 15:47:22
Java的IO流不仅可以对字符进行传输,也可以对对象进行传输,叫做对象的序列化和反序列化序列化:将对象转为方便传输的流(对象写入文件)反序列化:将流转换成对应的对象(把对象从文件中拿出)注意:如果我们需要将对象序列化到文件,首先需要让需要序列化对象对应的类实现序列化接口Serializable,该接口中没有任何方法和属性,仅仅只是一个标志,表示实现该接口的类是可以被序列化的;如果没有实现该接口就进行序列化,会报出NotSerializableException没有序列化的异常import java...

Java的IO流不仅可以对字符进行传输,也可以对对象进行传输,叫做对象的序列化和反序列化
Java中对象的序列化和反序列化操作
序列化:将对象转为方便传输的流(对象写入文件)
反序列化:将流转换成对应的对象(把对象从文件中拿出)

注意:如果我们需要将对象序列化到文件,首先需要让需要序列化对象对应的类实现序列化接口Serializable,该接口中没有任何方法和属性,仅仅只是一个标志,表示实现该接口的类是可以被序列化的;如果没有实现该接口就进行序列化,会报出NotSerializableException没有序列化的异常

import java.io.Serializable;

public class User implements Serializable {
	/**
	 * 用户名
	 */
	String userName;
	/**
	 * 密码
	 */
	String password;
	
	public User() {
		
	}
	
	public User(String deliverUserName,String deliverPassword) {
		userName = deliverUserName;
		password = deliverPassword;
	}

	@Override
	public String toString() {
		return "User [userName=" + userName + ", password=" + password + "]";
	}
	
}

1.对象进行序列化和反序列化

序列化和反序列化

类名 方法名 作用
序列化 ObjectOutputStream void write(Object obj) 将指定的对象序列化到流中
反序列化 ObjectInputStream Object readObject() 将流反序列化为对象并返回

序列化
序列化使用的是对象的输出流ObjectOutputStream(OutputStream out),使用时,传递的是一个字节输出流

	//创建对象序列化的对象
	ObjectOutputStream oos = null;
		try {
			oos = new ObjectOutputStream(new FileOutputStream("src/com/test/ser/user.txt",true));
		}catch (IOException e) {
			e.printStackTrace();
		}finally {
			//释放资源
			if(oos!=null) {
				try {
					oos.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}

成功创建对象的输出流后,我们就需要创建对象,然后吧对象进行序列化了

		//创建对象序列化的对象
		ObjectOutputStream oos = null;
		try {
			oos = new ObjectOutputStream(new FileOutputStream("src/com/test/ser/user.txt",true));
			//创建User的对象
			User user = new User("java","123456");
			//讲user序列化到文件中
			oos.writeObject(user);
			System.out.println("序列化成功");
		}catch (IOException e) {
			e.printStackTrace();
		}finally {
			//释放资源
			if(oos!=null) {
				try {
					oos.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}

序列化成功后,就可以在文件中看到我们序列化后的对象了
Java中对象的序列化和反序列化操作
注意:序列化的时候会写进一个头标,这头标就是定位的,当我们反序列化的时候,会从这个头标开始读取;每次序列化对象都会写入一个头标,当我们反序列化读取多个对象的时候就会报出StreamCorruptedException: invalid type code: AC的异常
为什么会这样呢?
因为序列化的时候都会调用writeStreamHeader()方法,该方法就是用于写头标的,每次序列化都会调用该方法
为了避免写入多个头标,所以我们可以实现他的一个子类,然后空实现这个方法来防止多个头标的出现

import java.io.IOException;
import java.io.ObjectOutputStream;
import java.io.OutputStream;

public class Sub extends ObjectOutputStream {

	public Sub(OutputStream out) throws IOException {
		super(out);
	}
	
	@Override
	protected void writeStreamHeader() throws IOException {
		
	}
}

空实现这个方法后,我们使用的时候,如果文件是空的时候就创建父类的对象,如果文件不为空的时候就可以创建子类的对象来防止出现多个头标

		//创建对象序列化的对象
		ObjectOutputStream oos = null;
		try {
			//创建文件类封装文件路径
			File file = new File("src/com/test/ser/user.txt");
			//判断是否为空
			if(file.length()<1) {
				oos = new ObjectOutputStream(new FileOutputStream(file,true));
			}else {
				oos = new Sub(new FileOutputStream(file,true));
			}
			//创建User的对象
			User user = new User("java","123456");
			//讲user序列化到文件中
			oos.writeObject(user);
			System.out.println("序列化成功");
		}catch (IOException e) {
			e.printStackTrace();
		}finally {
			//释放资源
			if(oos!=null) {
				try {
					oos.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}

通过一个File类中length()方法进行判断就可以根据需要进行不同对象的创建,防止了多个头标出现而导致的异常

反序列化
反序列化使用的是ObjectInputStream(InputStream in),使用时需要我们传递的是一个字节输入流

		//创建反序列化的对象
		ObjectInputStream ois = null;
		try {
			ois = new ObjectInputStream(new FileInputStream("src/com/test/ser/user.txt"));
		} catch (IOException e) {
			e.printStackTrace();
		}finally {
			//释放流
			if(ois!=null) {
				try {
					ois.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}

创建对象后就可以去指定文件拿取对象了

// 创建反序列化的对象
		ObjectInputStream ois = null;
		try {
			ois = new ObjectInputStream(new FileInputStream("src/com/test/ser/user.txt"));
			// 用于接收的对象
			Object obj = null;
			// 开始读取
			while ((obj = ois.readObject()) != null) {
				User user = (User) obj;
				System.out.println(user.toString());
			}
			/*
			 * 打印结果:
			 * User [userName=java, password=123456] 
			 * java.io.EOFException 
			 * atjava.io.ObjectInputStream$BlockDataInputStream.peekByte(ObjectInputStream.java:2917) 
			 * atjava.io.ObjectInputStream.readObject0(ObjectInputStream.java:1502) 
			 * atjava.io.ObjectInputStream.readObject(ObjectInputStream.java:422) 
			 * atcom.test.ser.UserDeserializableTest.main(UserDeserializableTest.java:16)
			 */
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			// 释放流
			if (ois != null) {
				try {
					ois.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}

通过打印结果可以看到报出了EOFException异常,这个异常表示的是,读取用的指针已经到达末尾了,所以可以多一个catch来异常解决即可

// 创建反序列化的对象
		ObjectInputStream ois = null;
		try {
			ois = new ObjectInputStream(new FileInputStream("src/com/test/ser/user.txt"));
			// 用于接收的对象
			Object obj = null;
			// 开始读取
			while ((obj = ois.readObject()) != null) {
				User user = (User) obj;
				System.out.println(user.toString());
			}
			/*
			 * 打印结果:
			 * User [userName=java, password=123456]
			 * 读取完毕
			 */
		} catch(EOFException e) {
			System.out.println("读取完毕");
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			// 释放流
			if (ois != null) {
				try {
					ois.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}

这样我们就可以通过反序列化拿到文件中的对象了

今天的分享就到这里了,欢迎大家来一起交流学习!

本文地址:https://blog.csdn.net/m0_48008264/article/details/107358660

相关标签: java学习 java