1.类实现Serializable接口
类必须实现该接口
private static final long SerialVersionUID =1;一定要加,防止你输出的文件被修改后没发读取
public class Dog implements Serializable {
private static final long SerialVersionUID =1;
private String name;
private Integer age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public Dog(String name, Integer age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Dog{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
2.编写序列化工具类
public class SerializableUtil {
/**
* 序列化
* @param t
* @param <T>
*/
public static <T> void outPutStream(File file, T t){
try(
//java1.7之后,关流的新方式,try()里面创建的流,会自动关闭无需手动
FileOutputStream output =new FileOutputStream(file,true);
ObjectOutputStream objectOutput = new ObjectOutputStream(output);
)
{
// if(file ==null || file.length()==0){
// ObjectOutputStream objectOutput = new ObjectOutputStream(output);
// objectOutput.writeObject(t);
// objectOutput.close();
// }else {
// MyObjectOutputStream objectOutput = new MyObjectOutputStream(output);
// objectOutput.writeObject(t);
// objectOutput.close();
// }
objectOutput.writeObject(t);
}catch (IOException e){
e.printStackTrace();
}
}
/**
* 反序列化读取文件类容并反序列化成对象
* @param file
* @param clazz 需要反序列化的对象的class对象(设置类型)
* @return
* @param <T>
*/
public static <T> List<T> inputPutStreamBack(File file,Class clazz){
List<T> t =new ArrayList<>();
try(
FileInputStream input = new FileInputStream(file);
ObjectInputStream objectInput= new ObjectInputStream(input)
)
{
Object o;
while ((o=objectInput.readObject())!=null){
if(o.getClass() == clazz){
t.add((T) o);
}
}
}catch (IOException | ClassNotFoundException e){
if(e instanceof EOFException){
}else {
e.printStackTrace();
}
}
return t;
}
}
3.测试(先将对象写入文件再读取出来)
public class test_05 {
public static void main(String[] args) {
File file = new File("F:\\测试\\dog.txt");
Dog dog = new Dog("小冰", 18);
SerializableUtil.outPutStream(file,dog);
// List<Dog> list = SerializableUtil.<Dog>inputPutStreamBack(file,Dog.class);
// System.out.println(list);
}
}
这里我们执行多次写入多个对象
写出文件是乱码,这里是正常,不用关。
测试读取文件中的对象
public class test_05 {
public static void main(String[] args) {
File file = new File("F:\\测试\\dog.txt");
// Dog dog = new Dog("小冰", 18);
// SerializableUtil.outPutStream(file,dog);
List<Dog> list = SerializableUtil.<Dog>inputPutStreamBack(file,Dog.class);
System.out.println(list);
}
}
结果:
出现该异常的原因:首先我们写入文件对象时都是以追加的方式写入文件的(newFileOutputStream(file,true)具体看上面工具类的代码,保证每次写入对象都是在原来的基础上增加),但是这里就出现了一个问题,我们每次写入时都是创建的一个新的ObjectOutputStream()导致我们每次写入时都会添加头部信息,相当于一个文件会有过个头部信息所以报错。
解决方式(推荐重写ObjectOutputStream的writeStreamHeader()方法):当文件为空的时候就写入头部信息,否者就不写。
我们创建一个自己的对象流,继承ObjectOutputStream,重写该方法(这里是直接return)
public class MyObjectOutputStream extends ObjectOutputStream {
public MyObjectOutputStream(OutputStream out) throws IOException {
super(out);
}
@Override
protected void writeStreamHeader() throws IOException {
return;
}
}
我们在工具类进行修改:(如果文件为空就用原始的,否者使用自己的)
4.再次测试
这里可能会抛出一个异常:EOFException
这个异常不用管,对我们没有一点印象,我们可以将它catch住,什么都不用管