【对象流ObjectOutputStream、ObjectInputStream的使用(踩坑点总结)】

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住,什么都不用管

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值