序列化多个对象和反序列化遍历一个文件中的所有对象原理讲解
程序员文章站
2024-03-11 22:46:01
...
若不进行处理,直接继续序列化添加对象进去。会在追加时继续写个头部的四个字节
直接读取时,报错!
下面和我们手动去掉;
再次运行!
成功读取
package com.gqzdev;
import com.gqzdev.bean.User;
import java.io.*;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
/**
* @ClassName: SeralizableTest
* @author: ganquanzhong
* @date: 2020/4/9 12:19
*/
public class SerializableTest implements Serializable {
public static void main(String[] args) throws IOException {
User user = new User(1001, "gqzdev-end"+new Date(), "女");
File file = new File("E:/ser");
/*
//序列化对象
serialize(user,file);
//反序列化
Object o =deserialize(file);
System.out.println(((User)o).toString());
*/
//序列化对象
//serializeAppend(user,file);
//反序列化
List<User> objList = deserializeObjList(file);
System.out.println(objList.size());
for (User user1:objList) {
System.out.println(user1.toString());
}
}
/**
* 序列化一个对象 , 并写到文件中
*/
public static void serialize(Object o,File file) throws IOException {
ObjectOutputStream stream =new ObjectOutputStream(new FileOutputStream(file));
try {
stream.writeObject(o);
stream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 序列化多个对象!!!
* 使用ObjectOutputStream会调用writeStreamHeader();
* 自动带上一个头aced 0005(占4个字节),然后每次读取都读完头然后在读内容。
* 导致追加数据时发生错误。解决方法就是先判断文件是否存在。如果不存在,就先创建文件。追加的情况就是当判断文件存在时,把那个4个字节的头aced 0005截取掉,然后在把对象写入到文件。这样就实现了对象序列化的追加
*
*
* 但是呢在读取的时候只有读取一次StreamHeader的,所以导致出错
*
* 解决方法,在序列化对象时,只保证写一次 StreamHeader
*/
public static void serializeAppend(Object obj,File file) throws IOException {
//如果文件存在 就追加到后面 append
boolean isexist=false;
if (file.exists()){
isexist=true;
}
FileOutputStream fileOutputStream=new FileOutputStream(file,true);
ObjectOutputStream objectOutputStream = new ObjectOutputStream(fileOutputStream);
// 每次new的时候都会写入一个StreamHeader,所以要把屁股后面的StreamHeader去掉
// 主要是处理fileOutputStream流的指针位置
// 可以说是文件的长度
long pos = 0;
if (isexist) {
// getChannel()返回此通道的文件位置,这是一个非负整数,它计算从文件的开始到当前位置之间的字节数
pos = fileOutputStream.getChannel().position() - 4;// StreamHeader有4个字节所以减去
// 将此通道的文件截取为给定大小
fileOutputStream.getChannel().truncate(pos);
System.out.println("追加成功~");
}
objectOutputStream.writeObject(obj);
// 关闭流
objectOutputStream.close();
}
/**
* 从文件中,反序列化读取到object中
*/
public static Object deserialize(File file) throws IOException{
ObjectInputStream stream = new ObjectInputStream(new FileInputStream(file));
try {
Object o = stream.readObject();
stream.close();
return o;
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return null;
}
public static List<User> deserializeObjList(File file) throws IOException{
List<User> list = new ArrayList<>();
FileInputStream fileInputStream = new FileInputStream(file);
ObjectInputStream stream = new ObjectInputStream(fileInputStream);
try {
//遍历所有对象 available() > 0代表流中还有对象
while (fileInputStream.available()>0){
Object o = stream.readObject();
System.out.println(((User)o).toString());
list.add((User)o);
}
System.out.println("read-->"+list.size());
stream.close();
return list;
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return null;
}
}
上一篇: python基础:细节问题梳理