第12讲-Java中的IO操作及对象的序列化与反序列化

时间:2023-03-08 17:52:30

1、知识点

1.1、课程回顾

第12讲-Java中的IO操作及对象的序列化与反序列化

1.2、本章重点

1.2.1  io操作

1.2.2  对象的序列化与反序列化

2、具体内容

2.1、Java IO

2.1.1、什么是IO

IO其实就是输入、输出

I  InputStream  输入流

O  OutputStream  输出流

  Java IO即Java输入输出系统。不管我们编写何种应用,都难免和各种输入输出相关的媒介打交道,其实和媒介进行IO的过程是十分复杂的,这要考虑的因素特别多,比如我们要考虑和哪种媒介进行IO(文件、控制台、网络),我们还要考虑具体和它们的通信方式(顺序、随机、二进制、按字符、按字、按行等等)。Java类库的设计者通过设计大量的类来攻克这些难题(Java设计者将复杂的IO操作封装成一个个方法,那么我们再去操作IO的时候,只需要调用他们写好的方法就可以了),这个类就位于java.io包中。

  在JDK1.4之后,为了提高Java IO的效率,Java又提供了一套新的IO,JavaNewIO简称JavaNIO。

第12讲-Java中的IO操作及对象的序列化与反序列化

2.1.3、IO分类

流:输入流  输出流

方式:字节流  字符流

IO具体的流

字节输入流InputStream、字节输出流OutputStream

字符输入流Reader、字符输出流Writer

我们如何来区分到底是输入还是输出:

读进来(reader in)  写出去(Writer Out)

第12讲-Java中的IO操作及对象的序列化与反序列化

2.1.4、字节输出流(将Java中的内容 输出 到文件中)

第12讲-Java中的IO操作及对象的序列化与反序列化

2.1.4、字节输入流(将文本中的内容 读取到Java内存)

第12讲-Java中的IO操作及对象的序列化与反序列化

2.1.5、循环读取数据(模拟大文件读取)

第12讲-Java中的IO操作及对象的序列化与反序列化

2.1.6、文件复制

第12讲-Java中的IO操作及对象的序列化与反序列化

2.1.7、异常处理

A  我们不讲异常抛出 而是选择try-catch

第12讲-Java中的IO操作及对象的序列化与反序列化

B  我们发现 关闭资源的代码是写到try中,有可能出现异常,此时close()无法执行。所以 我们需要将close()关闭资源的代码写到finally中

C  我们发现将close放到finally中的时候out和in报错。因为in和out的作用域不够。所以我们需要提高in和out的作用域。将in和out的定义写到try外面,赋值写到try的里面。

第12讲-Java中的IO操作及对象的序列化与反序列化

D  我们发现close()又报错了。这是因为close()也会出现异常--IOException。所以我们需要在finally中去处理close产生的异常

第12讲-Java中的IO操作及对象的序列化与反序列化

E  此时会出现一个隐藏的问题,就是当in和out如果为null的时候,此时执行close()代码会出现空指针异常。所以我们需要作非空判断

第12讲-Java中的IO操作及对象的序列化与反序列化

F  当我们的out在关闭的时候,如果出现异常,此时in就无法正常关闭了。所以 我们需要先在关闭out在out的finally中再去关闭in

第12讲-Java中的IO操作及对象的序列化与反序列化

总结:很麻烦  所以1.7推出了新的try-catch专门用来处理资源关闭。

2.1.8、字符流

第12讲-Java中的IO操作及对象的序列化与反序列化

2.1.9、包装流

第12讲-Java中的IO操作及对象的序列化与反序列化

2.2、序列化和反序列化

2.2.1、为什么需要序列化?

我们写的io都是将字符串与文件进行读写。如果我们有一个类People能不能将People对象写入到文件中呢?

是可以的,但是得用一个特殊的流派--对象流

第12讲-Java中的IO操作及对象的序列化与反序列化

此时会有异常(没有序列化异常):

java.io.NotSerializableException: com.ydj.test.People

此时 我们需要将People对象进行序列化。(理解:没有序列化,就不能进行io操作)

2.2.2、序列化的概念

Java序列化是指把Java对象转换为字节序列的过程

而Java反序列化是指把字节序列恢复为Java对象的过程

2.2.3、为什么需要序列化与反序列化

我们知道,当两个进程进行远程通信时,可以相互发送各种类型的数据,包括文本、图片、音频、视频等,而这些数据都会以二进制序列的形式在网络上传送。那么当两个Java进程进行通信时,能否实现进程间的对象传送呢?答案是可以的。如何做到呢?这就需要Java序列化与反序列化了。换句话说,一方面,发送方需要把这个Java对象转换为字节序列,然后在网络上传送;另一方面,接收方需要从字节序列中恢复Java对象。

当我们明晰了为什么需要Java序列化和反序列化后,我们很自然地会想到Java序列化的好处。其好处一是实现了数据的持久化(将数据存储到本地文件),通过序列化可以把数据永久地保存到硬盘上(通常存放在文件里),二是,利用序列化实现远程通信,即在网络上传送对象的字节序列

2.2.4、如何实现Java序列化与反序列化

1、JDK类库中序列化API

java.io.ObjectOutputStream:表示对象输出流

它的writeObject()方法源输入流中读取字节序列,再把它们反序列化成一个对象,并将其返回。

2、实现序列化的要求

只有实现了Serializable或Externalizable接口的类的对象才能被序列化,否则抛出异常。

问题:实现了序列化接口 某个类就能进行序列化和反序列化,但是 序列化接口中什么都没有?那么实现这个接口的意义在哪?

public interface Serializable{
}

问题:序列化ID

第12讲-Java中的IO操作及对象的序列化与反序列化

当我们将对象写入到文件中之后

在读取的时候 如果原先的类改变了,此时会报错

java.io.InvalidClassException: com.aaa.test.People; local class incompatible: stream classdesc serialVersionUID = 5569711604535381814, local class serialVersionUID = 453780806332567972

我们存储的时候,类会默认生成一个序列化id,当读取的时候,如果类发生改变,此时,序列化id也会发生变化,然后我们读取内容,此时版本id不一样,不匹配就报错。所以 我们需要 设定版本id,防止类发生变化,以前的东西无法读取。

(功能:聊天记录,游戏存档)

第12讲-Java中的IO操作及对象的序列化与反序列化