java序列化和反序列化工具_Java 序列化和反序列化工具类并解决StreamCorruptedException问题 | 学步园...

问题:

若通过ObjectOutputStream向一个文件中多次以追加的方式写入Object,为什么用ObjectInputStream读取这些Object时,会产生StreamCorruptedException

原因:

使用缺省的serializetion的实现时,一个ObjectOutputStream的构造和一个ObjectInputStream的构造必须一一对应,ObjectOutputStream的构造函数会向输出流中写入一个标识头,而ObjectInputStream会首先读入这个标志头,因此,多次以追加方式向一个文件写入Object时,该文件将会包含多个标志头,所以用ObjectInputStream来deserialize这个ObjectOutputStream时,将产生StreamCorruptedException。

解决方案:

构造一个ObjectOutputStream的子类,并覆盖writeStreamHeader()方法,被覆盖后的writeStreamHeader()方法应判断是否为首次向文件中写入Object,是则调用super.writeStreamHeader();若否,即以追加方式写入Object时,则应调用ObjectOutputStream.reset()方法。

案例:

创建测试类,在控制台上显示添加学生信息,要求程序循环运行,并依次提示接收学生类的所有属性值,保存到学生对象中,再将学生对象保存到集合对象中,并提示“是否继续添加(y/n):”,如果选择“y”则继续添加,否则退出循环,并将保存学生数据的集合对象通过序列化保存到“student.dat”文件中。然后实现从“student.dat”文件中反序列化保存学生数据的集合对象,并遍历打印输出学生信息。

解决StreamCorruptedException的错误:

/**

* 这个类可以避免StreamCorruptedException

* @author Liao

*

*/

public class MyObjectOutputStream extends ObjectOutputStream {

//无参构造函数

public MyObjectOutputStream() throws IOException, SecurityException {

super();

}

//有参构造函数

public MyObjectOutputStream(OutputStream out) throws IOException {

super(out);

}

/**

* 重写writeStreamHeader()方法

*/

@Override

protected void writeStreamHeader() throws IOException {

// TODO Auto-generated method stub

return ;

}

}

工具类:

public class SerializableUtil implements Serializable{

private static final long serialVersionUID = 1L;

/**

* 序列化对象

* 用户传一个Object类型对象,和要序列化到的文件路径即可进行序列化

* @param obj对象

* @param path 对象要被序列化到的文件路径

*/

public static void serializObject(Object obj,String path){

//创建文件

File file = new File(path);

//判断文件是否存在

if (!file.exists()){

//如果文件不存在,就创建文件

try {

file.createNewFile();

} catch (IOException e) {

e.printStackTrace();

}

}

//创建ObjectOutputStream

ObjectOutputStream objectOutputStream = null;

try {

//定义FileOutputStream,用于创建ObjectOutputStream

OutputStream outputStream = new FileOutputStream(file, true);

if (file.length() < 1){

objectOutputStream = new ObjectOutputStream(outputStream);

} else {

objectOutputStream = new MyObjectOutputStream(outputStream);

}

//把对象序列化到文件中

objectOutputStream.writeObject(obj);

} catch (Exception e) {

e.printStackTrace();

} finally {//强制关闭ObjectOutputStream

try {

objectOutputStream.close();

} catch (IOException e) {

e.printStackTrace();

}

}

}

/**

* 反序列化一个对象

*

* @param path 要反序列的文件的路径

* @return 返回一个被反序列化的对象

*/

@SuppressWarnings("resource")

public static Object unserializObject(String path){

//定义一个对象

Object obj = null;

//创建一个文件

File file = new File(path);

try {

//创建文件输入流

InputStream inputStream = new FileInputStream(file);

//通过文件输入流创建ObjectInputStream

ObjectInputStream objectInputStream = new ObjectInputStream(inputStream);

//获取一个对象

obj = objectInputStream.readObject();

} catch (Exception e) {

e.printStackTrace();

}

//返回一个对象

return obj;

}

/**

* 序列化一个集合

* 用户传一个集合和要序列化到的路径即可进行序列化

* @param collections 集合

* @param path 要序列化的路径

*/

public static void serializList(List collections,String path){

//创建文件

File file = new File(path);

//判断文件是否存在

if (!file.exists()){

//如果文件不存在,就创建文件

try {

file.createNewFile();

} catch (IOException e) {

e.printStackTrace();

}

}

//创建ObjectOutputStream

ObjectOutputStream objectOutputStream = null;

try {

//定义FileOutputStream,用于创建ObjectOutputStream

OutputStream outputStream = new FileOutputStream(file, true);

if (file.length() < 1){

objectOutputStream = new ObjectOutputStream(outputStream);

} else {

objectOutputStream = new MyObjectOutputStream(outputStream);

}

//遍历集合,然后把对象序列化到文件中

for (T collection : collections){

objectOutputStream.writeObject(collection);

}

} catch (Exception e) {

e.printStackTrace();

} finally {//强制关闭ObjectOutputStream

try {

objectOutputStream.close();

} catch (IOException e) {

e.printStackTrace();

}

}

}

/**

* 反序列化一个List集合

* 因为文件中有多个对象,如何在反序列化到末尾时,终止反序列化呢?

* 这里有一个技巧,我们可以通过一个死循环,一直读知道抛出EOFException时就break退出循环

* @param path路径

* @return 返回一个集合

*/

@SuppressWarnings("unchecked")

public static List unserializList(String path){

//创建一个文件

File file = new File(path);

//创建一个List集合用于存储反序列化后的对象

List collections = new ArrayList();

//定义ObjectInputStream

ObjectInputStream objectInputStream = null;

try {

//创建文件输入流

InputStream inputStream = new FileInputStream(file);

objectInputStream = new ObjectInputStream(inputStream);

//获取一个对象

while (true){

try {

//反序列化一个对象

T t = (T) objectInputStream.readObject();

//把该对象添加到集合中

collections.add(t);

} catch (EOFException e) {

break;

}

}

} catch (Exception e) {

e.printStackTrace();

} finally {

try {

objectInputStream.close();

} catch (IOException e) {

e.printStackTrace();

}

}

//返回一个对象

return collections;

}

}

测试类:

/**

* 测试类

* @author Liao

*

*/

public class SerializationTest {

public static void main(String[] args) {

Scanner in = new Scanner(System.in);

boolean flag = true;

//创建集合用于存放实体对象

List persons = new ArrayList();

while (flag) {

// 输入用户ID

System.out.print("请输入UID:");

Integer uid = in.nextInt();

// 输入用户名

System.out.print("请输入用户名:");

String uname = in.next();

// 输入性别

System.out.print("请输入性别:");

String gender = in.next();

//把Person对象存到集合中

persons.add(new Person(uid, uname, gender.equals("男")? Gender.MAN : Gender.WOMEN));

// 是否继续

System.out.print("是否继续? y/n:");

String ifContinue = in.next();

if (ifContinue.equals("n")) {

flag = false;

}

}

//序列化

SerializableUtil.serializList(persons, "D:\\liaozhongmin.txt");

//反序列化

List collections = SerializableUtil.unserializList("D:\\liaozhongmin.txt");

System.out.println(collections);

}

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值