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;
        }
    
    
    
    }
    
    
  • 相关阅读:
    周末之个人杂想(十三)
    PowerTip of the DaySorting Multiple Properties
    PowerTip of the DayCreate Remoting Solutions
    PowerTip of the DayAdd Help to Your Functions
    PowerTip of the DayAcessing Function Parameters by Type
    PowerTip of the DayReplace Text in Files
    PowerTip of the DayAdding Extra Information
    PowerTip of the DayPrinting Results
    Win7下IIS 7.5配置SSAS(2008)远程访问
    PowerTip of the DayOpening Current Folder in Explorer
  • 原文地址:https://www.cnblogs.com/gqzdev/p/12748465.html
Copyright © 2011-2022 走看看