序列化多個對象和反序列化遍歷一個文件中的所有對象原理講解

在這裏插入圖片描述
  若不進行處理,直接繼續序列化添加對象進去。會在追加時繼續寫個頭部的四個字節
在這裏插入圖片描述
直接讀取時,報錯!
在這裏插入圖片描述
在這裏插入圖片描述
下面和我們手動去掉;
在這裏插入圖片描述
再次運行!
成功讀取
在這裏插入圖片描述

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;
    }



}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章