JAVA IO - 一文搞懂 对象流 ObjectInputStream+ObjectOutputStream

1.由一个需求引入对象流

1.1 需求描述

1.将【基本数据类型 int a = 10】, 保存到文件中,并能够从文件中恢复;
2.将 【对象类型 new Dog("旺财",3)】,保存到文件中,并能够从文件中恢复。

1.2 需求分析

上面的两个需求可做如下分析:
1.需要将数据保存到文件中,(这个可以通过文件的写操作实现)
2.保存数据的同时,需要将 数据的类型也一起保存起来?(这个使用普通的流无法实现)
3.读取文件的时候,也要把 数据的类型读取出来?(这个使用普通的流无法实现)

1.3 需求解决

上述的需求,就是需要把 【基本数据类型】和【对象类型】进行【序列化】和【反序列化】。

2.补充-序列化的概念

【序列化】:就是 保存数据时,同时保存 数据的类型+数据值
【反序列化】:就是 读取数据时,同时读取 数据的类型+数据值
[注意]:
    在将对象进行序列化的时候,该对象的类必须是可序列化的。
    实现方式推荐 通过实现 Serializable 接口。

3.初识对象流

3.1 ObjectOutputStream

ObjectOutputStream : 提供序列化功能,可以实现保存 数据类型+数据值 到文件中去。
类的继承关系图如下:

JAVA IO - 一文搞懂 对象流 ObjectInputStream+ObjectOutputStream_第1张图片

3.2 ObjectInputStream

ObjectInputStream : 提供反序列化功能,可以实现 从文件中 读取 数据类型+数据值
类的继承关系图:

JAVA IO - 一文搞懂 对象流 ObjectInputStream+ObjectOutputStream_第2张图片

4.对象流的使用规则

在使用 对象流的时候,需要注意以下几个方面:

1.自定义的类需要 实现 Serializable 接口来确保可以进行序列化;
2.序列化的类中,建议添加 SerialVersionUID来提高版本的兼容性;
3.序列化对象时,默认将对象中的所有属性都进行序列化,但static 和 transient 修饰的成员除外;
4.序列化对象时,要求对象的属性的类型,也需要实现序列化接口;
5.序列化具有继承性,即一个类实现了序列化接口,则其子类也默认实现了序列化接口。
6.使用对象流在进行 序列化 和 反序列化 的时候,顺序要一致,即先写出去的,就要先读进来。

5.ObjectOutputStream使用案例

将 对象 序列化 保存

5.1 一个自定义类,实现了Serializable接口

package com.northcastle.domain;

import java.io.Serializable;

/**
 * author : northcastle
 * createTime:2022/1/8
 * 一个实现了序列化接口的类
 */
public class Dog implements Serializable {
    private String name;
    private Integer age;
    private Integer color;

    public Dog() {
    }

    public Dog(String name, Integer age, Integer color) {
        this.name = name;
        this.age = age;
        this.color = color;
    }

    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 Integer getColor() {
        return color;
    }

    public void setColor(Integer color) {
        this.color = color;
    }

    @Override
    public String toString() {
        return "Dog{" +
                "name='" + name + '\'' +
                ", age='" + age + '\'' +
                ", color=" + color +
                '}';
    }
}

5.2 对象流的使用

package com.northcastle.outputStream_;
// 注意 : 引入自定义的类,各位看官在实际写的时候注意自己的包路径即可
import com.northcastle.domain.Dog;

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;

/**
 * author : northcastle
 * createTime:2022/1/8
 * 对象输出流 : 保存类型+数据
 * 要保存的对象必须序列化
 */
public class ApplicationObjectOutputStream {
    public static void main(String[] args) {
        //1.声明一个输出的文件位置
        String filePath = "D:\\EDailyRoutine\\java-io-test\\ObjectOutputStream.data";
        //2.声明一个文件输出流
        FileOutputStream fos = null;
        //3.声明一个对象输出流
        ObjectOutputStream oos = null;

        try {
            //4.实例化 文件输出流
            fos = new FileOutputStream(filePath);
            //5.实例化 对象输出流
            oos = new ObjectOutputStream(fos);
            //6.执行写操作 : 进行序列化保存
            oos.writeInt(100); // 写 Integer
            oos.writeFloat(200.123f); // 写 Float
            oos.writeDouble(300.2d); // 写 Double
            oos.writeBoolean(false); // 写 Boolean
            oos.writeChar(95); // 写 Char
            oos.writeUTF("你好,我是对象输出流!"); // 写字符串 String
            oos.writeObject(new Dog("旺财",3,123)); // 写自定义的对象
            oos.writeUTF("============================"); // 写字符串


        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }finally{
            // 7.关闭最外层的 处理流 ObjectOutputStream
            if (oos != null){
                try {
                    oos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

    }

}

5.3 执行结果

找到输出的文件,打开后可以看到被序列化的内容:

JAVA IO - 一文搞懂 对象流 ObjectInputStream+ObjectOutputStream_第3张图片

6.ObjectInputStream使用案例

将数据 反序列化 读入到内存中.
此案例结合 上面的第5小结中序列化的数据。
【注】:反序列化的顺序,必须和 序列化的顺序相同!

6.1 读取代码

package com.northcastle.inputStream_;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.ObjectInputStream;

/**
 * author : northcastle
 * createTime:2022/1/8
 * 对象输入流 : 反序列化读取文件内容
 */
public class ApplicationObjectInputStream {
    public static void main(String[] args)  {
        //1.指定文件路径
        String filePath = "D:\\EDailyRoutine\\java-io-test\\ObjectOutputStream.data";
        //2.声明 文件输入流
        FileInputStream fis = null;
        //3.声明 对象输入流
        ObjectInputStream ois = null;

        try {
            //4.实例化 文件输入流
            fis = new FileInputStream(filePath);
            //5.实例化 对象输入流
            ois = new ObjectInputStream(fis);
            //6.执行反序列化操作:读取内容到程序中
            System.out.println(ois.readInt()); // 读 Integer
            System.out.println(ois.readFloat()); // 读 Float
            System.out.println(ois.readDouble()); // 读 Double
            System.out.println(ois.readBoolean()); // 读 Boolean
            System.out.println(ois.readChar()); // 读 Char
            System.out.println(ois.readUTF()); // 读 字符串 String
            System.out.println(ois.readObject()); // 读 对象
            System.out.println(ois.readUTF()); // 对 字符串 String

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }finally {
            //7.关闭对象输入流
            if (ois != null){
                try {
                    ois.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

6.2 运行结果

能够正确的读取到 文件中的内容

JAVA IO - 一文搞懂 对象流 ObjectInputStream+ObjectOutputStream_第4张图片

7.完成

Congratulations!
You are one step closer to success!

你可能感兴趣的:(JAVA,IO,java,java,io,对象流)