Java 对象处理流(ObjectOutputStream\ObjectInputStream)
创始人
2024-05-14 10:43:30
0

文章目录

  • 前言
  • 什么是对象流?
  • 基本介绍
  • ObjectOutputStream
  • ObjectInputStream
  • 对象处理流的使用细节

前言

处理流:是对一个已存在的流进行处理和封装,通过所封装的流的功能调用实现对数据的操作。而处理流中也有不同的分类,此片介绍的是处理流中的对象流。

如果对处理流流有疑问,可查看此博客或自行百度!
Java之节点流和处理流


什么是对象流?

对象流用于存储和读取基本数据类型数据和对象的处理流。它的强大之处在于可以把java中的对象写入数据源中,也能把对象从数据源中还原回来。为了让对象持久化(把对象存储到本地),可以使用java的对象流处理对象,把对象的内容写到本地存储的文件中,也可以从本地文件中读取出来。

比如说:将100(int/整形类型)和== 你好(String/字符串类型)== 写入某文本,写入的时候需要保持文件的100为int类型,你好为String类型,此时就需要用到对象流。(在保持一个数据值的时候,能够把它的数据类型保存起来)

在这里插入图片描述

也就是常说的序列化和反序列化。

  • 序列化:一个对象可以被表示为一个字节序列,该字节序列包括该对象的数据、有关对象的类型的信息和存储在对象中数据的类型(保存一个对象的时候,保存数据的值和数据类型就叫序列化)
  • 反序列化:将序列化对象写入文件之后,可以从文件中读取出来(恢复数据的时候,恢复数据的值和数据类型)

如果需要让某个对象支持序列化支持,则必须让其类是可序列化的。
为了让某个类是可序列化,该类必须实现如下两个接口之一:

  • Serializable:提供的通用数据保存和读取的接口(标记接口,没有方法)
  • Externalizable:该接口有方法需要实现,一般使用Serializable接口实现

基本介绍

  • ObjectOutputStream:提供序列化功能
  • ObjectInputStream:提供反序列化功能

功能::提供了对基本类型或对象类型的序列化和反序列化的方法

在这里插入图片描述
根据图可知,这两个类提供的构造器中采用了修饰器模式(传入的是各自父类的子类的实现对象,用什么方式操作,就传什么)

ObjectOutputStream

把对象转成字节数据的输出到文件中保存,对象的输出过程称为序列化,可实现对象的持久存储。

构造器

在这里插入图片描述
具体操作方法可以查看JDK文档或者百度
JDK8英文在线文档
JDK8中文在线文档

使用ObjectOutputStream序列化基本数据类型和一个Dog对象(自定义),并保存到data.dat文件中

序列化后,保存的文件格式不是纯文本的,而是按照它的格式来保存

  • Integer实现了Serializable接口(int自动装箱)
  • Boolean实现了Serializable接口(boolean自动装箱)
  • Character实现了Serializable接口(char自动装箱)
  • Double实现了Serializable接口(double自动装箱)
  • String实现了Serializable接口
    在这里插入图片描述

注意:这里ObjectOutputStream_ 和Dog文件在同一目录下,如果不在同一个目录下,则需要导包!

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;/*** 演示使用ObjectOutputStream的使用*/
public class ObjectOutputStream_ {public static void main(String[] args) {String filePath = "E:\\data.dat";//ObjectOutputStream os = null;try {os = new ObjectOutputStream(new FileOutputStream(filePath));//序列化数据E:\\data.datos.writeInt(100);//int -> Integer(自动装箱)os.writeBoolean(true);//boolean -> Boolean(自动装箱)os.writeChar('a');//char -> Characteros.writeDouble(3.14);//double -> Doubleos.writeUTF("hello");//String//保存自定义对象os.writeObject(new Dog("jack", 4));} catch (IOException e) {e.printStackTrace();} finally {try {os.close();//释放资源System.out.println("数据保存完毕(序列化)");} catch (IOException e) {e.printStackTrace();}}}
}
  • Dog类
import java.io.Serializable;public class Dog implements Serializable {private String name;private int age;public Dog(String name, int age) {this.name = name;this.age = age;}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}
}

文件打开乱码属于正常现象,此代码执行之后文件中内容:
 w d a@ 窺雲 hellosr com.chapter19.outputstream_.DogP戶嶏+/> I ageL namet Ljava/lang/String;xp t jack

ObjectInputStream

反序列化流,将之前使用 ObjectOutputStream 序列化的原始数据恢复为对象,以流的方式读取对象。

构造器

在这里插入图片描述

具体操作方法可以查看JDK文档或者百度
JDK8英文在线文档
JDK8中文在线文档

  • 读取(反序列化)的顺序要和保存数据(序列化)的顺序一致,否则会出现异常。

恢复ObjectOutputStream输出到文件中的数据和类型,恢复到程序中(反序列化)

注意:自定义类读取时,需要将定义的类拷贝到工程(并且公有化)或者导包

  • 这里我使用的是导包
import com.chapter19.outputstream_.Dog;import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;public class ObjectInputStream_ {public static void main(String[] args) {String filePath = "E:\\data.dat";//指定反序列化的文件ObjectInputStream oi = null;try {oi = new ObjectInputStream(new FileInputStream(filePath));System.out.println(oi.readInt());System.out.println(oi.readBoolean());System.out.println(oi.readChar());System.out.println(oi.readDouble());System.out.println(oi.readUTF());Object obj = oi.readObject();System.out.println(obj);System.out.println("运行类型" + obj.getClass());Dog o1 = (Dog) obj;System.out.println(o1.getName());} catch (IOException | ClassNotFoundException e) {e.printStackTrace();} finally {try {oi.close();} catch (IOException e) {e.printStackTrace();}}}
}

控制台输出如下:
a
3.14
hello
com.chapter19.outputstream_.Dog@6f496d9f
运行类型class com.chapter19.outputstream_.Dog
jack


对象处理流的使用细节

  1. 读写顺序要一致,如果顺序出错,则会抛出异常

  2. 要求序列化或反序列化对象,需要实现Serializable接口

  3. 序列化的类中建议添加SerialVersionUID,提高版本的兼容性
    在这里插入图片描述
    当文件中添加新的内容需要执行时,JVM会认为这个文件只是这个个版本的修改版或升级版,而不会认为是一个新的类(与游戏更新类似)

  4. 序列化对象时,默认将里面所有属性都进行序列化,但除了static或transient修饰的成员(被transient修饰的变量不参与序列化和反序列化)

  5. 序列化对象时,要求里面属性的类型也需要实现序列化接口(int、char、double等会自动封装类型)

  6. 序列化具有可继承性,也就是如果某类已经实现了序列化,则它的所有子类也已经默认实现了序列化


相关内容

热门资讯

监控摄像头接入GB28181平... 流程简介将监控摄像头的视频在网站和APP中直播,要解决的几个问题是:1&...
Windows10添加群晖磁盘... 在使用群晖NAS时,我们需要通过本地映射的方式把NAS映射成本地的一块磁盘使用。 通过...
protocol buffer... 目录 目录 什么是protocol buffer 1.protobuf 1.1安装  1.2使用...
在Word、WPS中插入AxM... 引言 我最近需要写一些文章,在排版时发现AxMath插入的公式竟然会导致行间距异常&#...
【PdgCntEditor】解... 一、问题背景 大部分的图书对应的PDF,目录中的页码并非PDF中直接索引的页码...
Fluent中创建监测点 1 概述某些仿真问题,需要创建监测点,用于获取空间定点的数据࿰...
educoder数据结构与算法...                                                   ...
MySQL下载和安装(Wind... 前言:刚换了一台电脑,里面所有东西都需要重新配置,习惯了所...
修复 爱普生 EPSON L4... L4151 L4153 L4156 L4158 L4163 L4165 L4166 L4168 L4...
MFC文件操作  MFC提供了一个文件操作的基类CFile,这个类提供了一个没有缓存的二进制格式的磁盘...