zoukankan      html  css  js  c++  java
  • 序列化多个对象和反序列化遍历一个文件中的所有对象原理讲解

    在这里插入图片描述
      若不进行处理,直接继续序列化添加对象进去。会在追加时继续写个头部的四个字节
    在这里插入图片描述
    直接读取时,报错!
    在这里插入图片描述
    在这里插入图片描述
    下面和我们手动去掉;
    在这里插入图片描述
    再次运行!
    成功读取
    在这里插入图片描述

    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;
        }
    
    
    
    }
    
    
  • 相关阅读:
    起步学习软件开发(.Net 方向)的指导
    Lesktop开源JS控件库
    软件岗位职责
    asp.net 获取网站根目录总结
    微软是怎样做测试的
    打造WebIM
    CodeSmith 系列一
    Crack .NET
    Visual Studio IDE 实用小技巧3
    程序员公司的选择
  • 原文地址:https://www.cnblogs.com/gqzdev/p/12748465.html
Copyright © 2011-2022 走看看