Java基础8—IO流与IO多路复用

文章目录

  • 1. IO流
    • 1.1 IO流的分类
    • 1.2 常见IO流
      • 1.2.1 InputStream
      • 2.2 字节输出流
      • 2.2.3 字符输入流
      • 2.2.4 字符输出流
    • 2.3 字节流和字符流的区别
  • 2. 序列化
    • 2.1 序列化的实现
    • 2.2 反序列化的实现
    • 2.3 序列化版本号**serialVersionUID**
    • 2.4 序列化使用场景
  • 3. IO模型
    • 3.1 BIO
    • 3.2 NIO
    • 3.3 IO多路复用
      • 3.3.1 select
      • 3.3.2 Poll
      • 3.3.3 Epoll
    • 3.4 异步IO
      • 3.4.1 io_uring

1. IO流

几乎所有的程序都离不开信息的输入和输出,比如从键盘读取数据,从文件中获取或者向文件中存入数据,在显示器上显示数据。这些情况下都会涉及有关输入/输出的处理。

在Java中,把这些不同类型的输入、输出源抽象为流(Stream),其中输入或输出的数据称为数据流(Data Stream),用统一的接口来表示。

1.1 IO流的分类

数据流是指一组有顺序的、有起点和终点的字节集合

  • 按照流的流向分,可以分为输入流和输出流。注意:这里的输入、输出是针对程序来说的。
    • 输出:把程序(内存)中的内容输出到磁盘、光盘等存储设备中。
    • 输入:读取外部数据(磁盘、光盘等存储设备的数据)到程序(内存)中。
  • 按处理数据单位不同分为字节流和字符流。
    • 字节流:每次读取(写出)一个字节,当传输的资源文件有中文时,就会出现乱码
    • 字符流:每次读取(写出)两个字节,有中文时,使用该流就可以正确传输显示中文。
  • 按照流的角色划分为节点流和处理流。
    • 节点流:从或向一个特定的地方(节点)读写数据。如FileInputStream。
    • 处理流(包装流):是对一个已存在的流的连接和封装,通过所封装的流的功能调用实现数据读写。如BufferedReader。

下图是Java IO 流的整体架构图:

Java基础8—IO流与IO多路复用_第1张图片

1.2 常见IO流

1.2.1 InputStream

java.io 包下所有的字节输入流都继承自 InputStream,并且实现了其中的方法。InputStream 中提供的主要数据操作方法如下:

  • int read():从输入流中读取一个字节的二进制数据。
  • int read(byte[] b):将多个字节读到数组中,填满整个数组。
  • int read(byte[] b, int off, int len):从输入流中读取长度为 len 的数据,从数组 b 中下标为 off 的位置开始放置读入的数据,读完返回读取的字节数。
  • void close():关闭数据流。
  • int available():返回目前可以从数据流中读取的字节数(但实际的读操作所读得的字节数可能大于该返回值)。
  • long skip(long l):跳过数据流中指定数量的字节不读取,返回值表示实际跳过的字节数。

对数据流中字节的读取通常是按从头到尾顺序进行的,如果需要以反方向读取,则需要使用回推(Push Back)操作。 在支持回推操作的数据流中经常用到如下几个方法:

  • boolean markSupported():用于测试数据流是否支持回推操作,当一个数据流支持 mark() 和 reset() 方法时,返回 true,否则返回 false。
  • void mark(int readlimit):用于标记数据流的当前位置,并划出一个缓冲区,其大小至少为指定参数的大小。
  • void reset():将输入流重新定位到对此流最后调用 mark() 方法时的位置。

字节输入流 InputStream 有很多子类,日常开发中,经常使用的一些类见下图:

Java基础8—IO流与IO多路复用_第2张图片

2.2 字节输出流

与字节输入流类似,java.io 包下所有字节输出流大多是从抽象类 OutputStream 继承而来的。OutputStream 提供的主要数据操作方法:

  • void write(int i):将字节 i 写入到数据流中,它只输出所读入参数的最低 8 位,该方法是抽象方法,需要在其输出流子类中加以实现,然后才能使用。
  • void write(byte[] b):将数组 b 中的全部 b.length 个字节写入数据流。
  • void write(byte[] b, int off, int len):将数组 b 中从下标 off 开始的 len 个字节写入数据流。元素 b[off] 是此操作写入的第一个字节,b[off + len - 1] 是此操作写入的最后一个字节。
  • void close():关闭输出流。
  • void flush():刷新此输出流并强制写出所有缓冲的输出字节。

为了加快数据传输速度,提高数据输出效率,输出数据流会在提交数据之前把所要输出的数据先暂时保存在内存缓冲区中,然后成批进行输出,每次传输过程都以某特定数据长度为单位进行传输,在这种方式下,数据的末尾一般都会有一部分数据由于数量不够一个批次,而存留在缓冲区里,调用 flush() 方法可以将这部分数据强制提交。

你可能感兴趣的:(Java基础,java)