聊聊什么是IO流

目录

  • Java IO
    • IO 基础
      • Java IO 流了解吗?
    • IO 设计模式
      • 1、装饰器模式
      • 2、适配器模式
      • 适配器模式和装饰器模式有什么区别呢?
      • 3、工厂模式
      • 4、观察者模式
    • IO 模型
      • 有哪些常见的 IO 模型?
        • BIO(Blocking I/O)
        • NIO (Non-blocking/New I/O)
        • AIO (Asynchronous I/O)
      • BIO、NIO、AIO 有什么区别?
    • 参考

Java IO

IO 基础

Java IO 流了解吗?

IO 即 Input/0utput ,输入和输出。数据输入到计算机内存的过程即输入,反之输出到外部存储 (比如数据库,文件,远程主机)的过程即输出。

数据传输过程类似于水流,因此称为 IO 流。

  • IO 流在 java 中分为输入流输出流
  • 而根据数据的处理方式又分为字节流字符流

Java IO 流的 40 多个类都是从如下 4 个抽象类基类中派生出来的:

  • InputStream/Reader: 所有的输入流的基类,前者是字节输入流,后者是字符输入流。
  • OutputStream/Writer: 所有输出流的基类,前者是字节输出流,后者是字符输出流

IO 设计模式

1、装饰器模式

装饰器模式是一种结构型设计模式,允许在运行时动态地将责任附加到对象上。

是一种通过组合替代继承来扩展原始类的功能,可以在不改变原有对象的情况下增强其功能的模式。

// 输入
// 将FileInputStream对象 装饰 成了一个带有缓冲区的输入流对象
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(fileName));
// 将带有缓冲区的输入流对象 再次装饰 成了一个能够处理ZIP文件的输入流对象
ZipInputStream zis = new ZipInputStream(bis);// 输出
// 将FileOutputStream对象 装饰 成了一个带有缓冲区的输出流对象
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(fileName));
// 将带有缓冲区的输出流对象 再次装饰 成了一个能够处理ZIP文件的输出流对象。
ZipOutputStream zipOut = new ZipOutputStream(bos);

其中 BufferedInputStream、ZipInputStream、BufferedOutputStream 和 ZipOutputStream 都是 Java 中的装饰器类。

2、适配器模式

可以用于将不兼容的类或接口转换为兼容的类或接口,从而使它们能够协同工作。

适配器模式中存在被适配的对象或者类称为 适配者(Adaptee) ,作用于适配者的对象或者类称为适配器(Adapter)

// InputStreamReader 是适配器,用于将 FileInputStream 实现的字节流接口适配成字符流接口
InputStreamReader isr = new InputStreamReader(new FileInputStream(fileName), "UTF-8");
// BufferedReader 增强 InputStreamReader 的功能(装饰器模式)
BufferedReader bufferedReader = new BufferedReader(isr);

适配器模式和装饰器模式有什么区别呢?

适配器模式和装饰器模式虽然都属于结构型设计模式,但是它们的设计目的和实现方式有所不同。

设计目的

  1. 适配器模式(Adapter Pattern)的设计目的是:将一个类的接口转换为客户端所期望的另一个接口,以满足客户端的需求。适配器模式通常用于解决接口不兼容的问题,它通过一个适配器来将一个类的接口转换为另一个接口,使得客户端可以像调用另一个接口一样来调用原来的接口。适配器模式通常是在已有的系统中进行接口升级或者系统集成时使用的。
  2. 装饰器模式(Decorator Pattern)的设计目的是:在不改变原有对象的基础上,动态地给对象添加一些新的功能。装饰器模式通常用于解决类的功能扩展问题,它通过在原有对象的基础上添加一个装饰器来为对象添加新的功能,使得客户端可以在不改变原有对象的情况下使用新的功能。装饰器模式通常是在需要为一个对象动态地添加一些功能时使用的。

实现方式

适配器模式通常是通过一个适配器类来转换接口,而装饰器模式通常是通过继承或者组合的方式来实现功能的添加

  • 装饰器类需要跟原始类继承相同的抽象类或者实现相同的接口。(同一个父类,字节流 – 字节流)
  • 适配器和适配者两者不需要继承相同的抽象类或者实现相同的接口。(不同的父类,字符流 – 字节流)

3、工厂模式

Java IO 中的工厂模式指的是:通过工厂类来创建不同类型的输入输出流对象。从而实现更加灵活的 IO 操作。

常用的 IO 工厂模式有 InputStreamFactory、OutputStreamFactory、ReaderFactory 和 WriterFactory 等。

代码示例如下:

  1. 首先创建四个工厂对象:InputStreamFactory、OutputStreamFactory、ReaderFactory 和 WriterFactory,分别用于创建输入流、输出流、字符输入流和字符输出流。
  2. 然后,通过调用它们的 create 方法,创建了对应的输入流对象和输出流对象
  3. 最后,使用创建的输入流对象和输出流对象,对文件进行读写操作
public class IOFactoryDemo {public static void main(String[] args) {// 创建输入流工厂对象InputStreamFactory inputStreamFactory = new FileInputStreamFactory();// 创建输出流工厂对象OutputStreamFactory outputStreamFactory = new FileOutputStreamFactory();// 创建字符输入流工厂对象ReaderFactory readerFactory = new FileReaderFactory();// 创建字符输出流工厂对象WriterFactory writerFactory = new FileWriterFactory();// 创建文件输入流对象InputStream inputStream = inputStreamFactory.createInputStream("C:\\myfiles\\input.txt");// 创建文件输出流对象OutputStream outputStream = outputStreamFactory.createOutputStream("C:\\myfiles\\output.txt");// 创建字符输入流对象Reader reader = readerFactory.createReader("C:\\myfiles\\input.txt");// 创建字符输出流对象Writer writer = writerFactory.createWriter("C:\\myfiles\\output.txt");// 从文件输入流中读取数据try (BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream))) {String line;while ((line = bufferedReader.readLine()) != null) {System.out.println(line);}} catch (IOException e) {e.printStackTrace();}// 向文件输出流中写入数据try (BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(outputStream)) {String data = "Hello, world!";byte[] bytes = data.getBytes();bufferedOutputStream.write(bytes);} catch (IOException e) {e.printStackTrace();}// 从字符输入流中读取数据try (BufferedReader bufferedReader = new BufferedReader(reader)) {String line;while ((line = bufferedReader.readLine()) != null) {System.out.println(line);}} catch (IOException e) {e.printStackTrace();}// 向字符输出流中写入数据try (BufferedWriter bufferedWriter = new BufferedWriter(writer)) {String data = "Hello, world!";bufferedWriter.write(data);} catch (IOException e) {e.printStackTrace();}}
}

使用工厂模式的好处是什么?

通过工厂模式创建输入输出流对象,可以避免直接使用具体的类来创建对象,降低了客户端和具体类的耦合度,提高了系统的灵活性和扩展性。此外,工厂方法还可以对输入输出流对象进行统一管理和控制,从而实现一些特定的功能,如数据压缩、加密等。

4、观察者模式

IO 观察者模式是一种设计模式,用于监控文件或目录的变化

在 Java 中,可以使用 java.nio.file 包中的 WatchService 类来实现 IO 观察者模式。

WatchService 类充当观察者,用于监控指定目录中的文件或子目录的变化。当目录中的文件或子目录发生变化时,WatchService通过 Path 事件通知注册的观察者

具体地说,使用 WatchService 实现 IO 观察者模式的步骤如下:

  1. 创建一个 WatchService 对象,通过 Path 对象的 register() 方法将其注册到需要监控的目录中。

  2. 创建一个线程,不断从 WatchService 对象中获取事件,并处理这些事件。

  3. WatchService 对象检测到目录中的文件或子目录发生变化时,会生成一个 Path 事件,并将其添加WatchService 对象的事件队列中。

  4. 在处理事件的线程中,可以通过 WatchEvent 对象获取事件类型、事件发生的路径等信息,并根据这些信息进行相应的处理

/*** 文件观察者类,用于监测指定目录中文件的变化*/
public class FileWatcher implements Runnable {private Path path;              // 目录路径private WatchService watchService;  // WatchService对象用于监测目录中文件的变化/*** 构造函数,创建一个FileWatcher对象* @param path 目录路径* @throws IOException 抛出IO异常*/public FileWatcher(Path path) throws IOException {this.path = path;// 获取默认的WatchService对象this.watchService = FileSystems.getDefault().newWatchService();// 注册监测事件类型this.path.register(watchService, StandardWatchEventKinds.ENTRY_CREATE, StandardWatchEventKinds.ENTRY_DELETE, StandardWatchEventKinds.ENTRY_MODIFY);}/*** run方法,用于启动监测线程*/@Overridepublic void run() {try {while (true) {// 获取WatchKey对象,它代表了被监测的目录中的事件队列WatchKey key = watchService.take();// 遍历事件队列for (WatchEvent<?> event : key.pollEvents()) {// 输出事件类型和受影响的文件名System.out.println("Event kind: " + event.kind() + ". File affected: " + event.context() + ".");}// 重置WatchKey对象,以便继续监测key.reset();}} catch (InterruptedException e) {e.printStackTrace();}}/*** main方法,用于启动文件监测程序*/public static void main(String[] args) throws IOException {// 创建监测的目录路径Path path = Paths.get("/path/to/monitor");// 创建FileWatcher对象FileWatcher fileWatcher = new FileWatcher(path);// 创建监测线程,并启动Thread thread = new Thread(fileWatcher);thread.start();}
}

IO 观察者模式可以用于监控文件或目录的变化,从而实现一些特定的功能,如自动备份、自动同步等。在实际开发中,IO 观察者模式可以提高代码的可维护性和可扩展性,使得代码更加灵活。

IO 模型

有哪些常见的 IO 模型?

Java 中有 3 种常见 IO 模型:

BIO(Blocking I/O)

BIO 属于同步阻塞 IO 模型

同步阻塞 IO 模型中,应用程序发起 read 调用后,会一直阻塞,直到内核把数据拷贝到用户空间。

在这里插入图片描述

NIO (Non-blocking/New I/O)

NIO 属于同步非阻塞 IO 模型

NIO(New I/O)是 Java NIO(New Input/Output)API 的简称,是 Java SE 1.4 中引入的一组新的 I/O API,用于替代 Java 标准 I/O API(java.io 包)中的一部分功能。

NIO 提供了一种基于通道(Channel)和缓冲区(Buffer)的 I/O 模型,相较于传统的基于流的 I/O 模型,它具有更高的性能和更好的扩展性。

  • 通道表示数据源与目标之间的连接,可以用于读取和写入数据。
  • 缓冲区则是存储数据的区域,数据通过缓冲区进行传输。
    在这里插入图片描述

在同步非阻塞I/O模型中,应用程序发起 read 调用后(轮询操作),线程不会被阻塞。相反,线程会立即返回,并继续执行后续的操作,而不必等待数据从内核空间拷贝到用户空间。

通过不断发起 read 调用来检查是否有新的数据可用

但是它可以通过多路复用技术来实现高效的 IO 操作,减少无效的系统调用,减少了对 CPU 资源的消耗。

IO 多路复用模型中,线程首先发起 select 调用,询问内核数据是否准备就绪,等内核把数据准备好了,用户线程再发起 read 调用。read 调用的过程(数据从内核空间 -> 用户空间)还是阻塞的。
在这里插入图片描述

AIO (Asynchronous I/O)

AIO 是异步 IO 模型

异步 IO 是基于事件和回调机制实现的,也就是应用操作之后会直接返回,不会堵塞在那里,当后台处理完成,操作系统会通知相应的线程进行后续的操作。
在这里插入图片描述

BIO、NIO、AIO 有什么区别?

它们主要的区别在于数据的读取和处理方式不同。

  1. BIO(Blocked IO):**BIO 是同步阻塞 I/O 模型。**在该模型下,所有的 I/O 操作都是阻塞的,即当一个线程在进行 I/O 操作时,它会一直等待直到数据准备就绪或者发生异常。(只会发起一次 read 调用,但会阻塞)

    BIO 模型适用于连接数比较少且通信线程比较短的场景,例如传统的客户端/服务器模型。

  2. NIO(Non-Blocked IO):**NIO 是同步非阻塞 I/O 模型。**在该模型下,所有的 I/O 操作都是非阻塞的,即当一个线程在进行 I/O 操作时,它会立即返回一个特定的状态(通常是非阻塞状态,如EAGAIN或EWOULDBLOCK),表示当前没有可用的数据,而不会等待数据准备就绪。(会一直发起 read 调用)

    NIO 模型适用于连接数比较多且通信线程比较长的场景,例如聊天室和在线游戏。

  3. AIO(Asynchronous IO):**AIO 是异步非阻塞 I/O 模型。**在该模型下,所有的 I/O 操作都是异步的,即当一个线程在进行 I/O 操作时,它不需要等待数据准备就绪,而是通过回调函数的方式来处理数据。(只会发起一次 read 调用)

    AIO 模型适用于连接数非常多且通信线程比较长的场景,例如高性能的网络服务器。

总的来说,

  • BIO 模型的开销比较大,但是编程模型比较简单;(性能较低)
  • NIO 模型的开销比较小,但是编程模型比较复杂;(性能较高)
  • AIO 模型相对于 NIO 模型来说,编程模型更为简单,但是在性能方面与 NIO 模型相当或者略逊一筹。(综合型)

参考

Java基础常见面试题总结(下)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/190003.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

51单片机的智能加湿器控制系统【含proteus仿真+程序+报告+原理图】

1、主要功能 该系统由AT89C51单片机LCD1602显示模块DHT11湿度传感器模块继电器等模块构成。主要适用于智能自动加湿器、湿度保持、湿度控制等相似项目。 可实现基本功能: 1、LCD1602液晶屏实时显示湿度信息 2、DHT11采集湿度 3、按键可以调节适宜人体湿度的阈值范围&#xff0…

西南科技大学模拟电子技术实验三(BJT单管共射放大电路测试)预习报告

一、计算/设计过程 说明:本实验是验证性实验,计算预测验证结果。是设计性实验一定要从系统指标计算出元件参数过程,越详细越好。用公式输入法完成相关公式内容,不得贴手写图片。(注意:从抽象公式直接得出结果,不得分,页数可根据内容调整) 二、画出并填写实验指导书上…

京东数据运营-京东数据开放平台-鲸参谋10月粮油调味市场品牌店铺销售数据分析

鲸参谋监测的京东平台10月份料油调味市场销售数据已出炉&#xff01; 根据鲸参谋数据显示&#xff0c;今年10月份&#xff0c;京东平台粮油调味市场的销量将近4600万&#xff0c;环比增长约10%&#xff0c;同比降低约20%&#xff1b;销售额将近19亿&#xff0c;环比增长约4%&am…

Apache Flink(一):Apache Flink是什么?

&#x1f3e1; 个人主页&#xff1a;IT贫道_大数据OLAP体系技术栈,Apache Doris,Clickhouse 技术-CSDN博客 &#x1f6a9; 私聊博主&#xff1a;加入大数据技术讨论群聊&#xff0c;获取更多大数据资料。 &#x1f514; 博主个人B栈地址&#xff1a;豹哥教你大数据的个人空间-豹…

五、ZooKeeper的shell操作

目录 1、客户端连接 2、shell基本操作 2.1 操作命令

力扣225-用队列实现栈

文章目录 力扣225-用队列实现栈示例代码实现总结收获 力扣225-用队列实现栈 示例 代码实现 class MyStack {Queue<Integer>queue1;Queue<Integer>queue2;public MyStack() {queue1new LinkedList<Integer>();queue2new LinkedList<Integer>();}public…

【LeetCode:1094. 拼车 | 差分数组】

&#x1f680; 算法题 &#x1f680; &#x1f332; 算法刷题专栏 | 面试必备算法 | 面试高频算法 &#x1f340; &#x1f332; 越难的东西,越要努力坚持&#xff0c;因为它具有很高的价值&#xff0c;算法就是这样✨ &#x1f332; 作者简介&#xff1a;硕风和炜&#xff0c;…

【高效开发工具系列】Hutool Http工具类

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…

PDF转WORD

无环境的&#xff0c;windows可下载可执行文件&#xff1a;https://download.csdn.net/download/shfei10100/88588106 有python运行环境的&#xff0c;可自行运行&#xff1b; 代码如下&#xff1a; from pdf2docx import Converterimport tkinter as tk from tkinter impor…

Windows11系统下内存占用率过高如何下降

. # &#x1f4d1;前言 本文主要是win11系统下CPU占用率过高如何下降的文章&#xff0c;如果有什么需要改进的地方还请大佬指出⛺️ &#x1f3ac;作者简介&#xff1a;大家好&#xff0c;我是青衿&#x1f947; ☁️博客首页&#xff1a;CSDN主页放风讲故事 &#x1f304;每日…

每日一题:NowCower-JZ64.求1+2+3+...+n

每日一题系列&#xff08;day 10&#xff09; 前言&#xff1a; &#x1f308; &#x1f308; &#x1f308; &#x1f308; &#x1f308; &#x1f308; &#x1f308; &#x1f308; &#x1f308; &#x1f308; &#x1f308; &#x1f308; &#x1f308; &#x1f50e…

Git and solve the problem denied to xx

创建仓库 配置Git git config user.name git config user.email git config MINGW64 /e/GithubCode $ git config --global user.name "name"MINGW64 /e/GithubCode $ git config --global user.email "mailxx.com" 生产ssh ssh-keygen -t rsa -C “xx…

选择排序以及改进方案

选择排序以及改进方案 介绍&#xff1a; 选择排序是一种简单直观的排序算法&#xff0c;它的基本思想是在未排序序列中选择最小&#xff08;或最大&#xff09;的元素&#xff0c;然后将其放在已排序序列的末尾。选择排序的过程就像是每次从待排序的元素中选择最小的一个&…

Linux:锁定部分重要文件,防止误操作

一、情景描述 比如root用户或者拥有root权限的用户&#xff0c;登陆系统后&#xff0c;通过useradd指令&#xff0c;新增一个用户。 而我们业务限制&#xff0c;只能某一个人才有权限新增用户。 那么&#xff0c;这个时候&#xff0c;我们就用chattr来锁定/etc/passwd文件&…

六、ZooKeeper Java API操作

目录 1、引入maven坐标 2、节点的操作 这里操作Zookeeper的JavaAPI使用的是一套zookeeper客户端框架 Curator ,解决了很多Zookeeper客户端非常底层的细节开发工作 。 Curator包含了几个包:

使用K-means把人群分类

1.前言 K-mean 是无监督的聚类算法 算法分类&#xff1a; 2.实现步骤 1.数据加工&#xff1a;把数据转为全数字&#xff08;比如性别男女&#xff0c;转换为0 和 1&#xff09; 2.模型训练 fit 3.预测 3.代码 原数据类似这样(source&#xff1a;http:img-blog.csdnimg.cn…

CleanMyMac X2024Macos强大的系统优化工具

都说苹果的闪存是金子做的&#xff0c;这句话并非空穴来风&#xff0c;普遍都是256G起步&#xff0c;闪存没升级一个等级&#xff0c;价格都要增加上千元。昂贵的价格让多数消费者都只能选择低容量版本的mac。而低容量的mac是很难满足用户的需求的&#xff0c;伴随着时间的推移…

FL Studio2024破解版激活注册码

FL Studio2024是功能强大的音乐制作解决方案&#xff0c;使用旨在为用户提供一个友好完整的音乐创建环境&#xff0c;让您能够轻松创建、管理、编辑、混合具有专业品质的音乐&#xff0c;一切的一切都集中在一个软件中&#xff0c;只要您想&#xff0c;只要您需要&#xff0c;它…

深入浅出 Linux 中的 ARM IOMMU SMMU III

系统 I/O 设备驱动程序通常调用其特定子系统的接口为 DMA 分配内存&#xff0c;但最终会调到 DMA 子系统的 dma_alloc_coherent()/dma_alloc_attrs() 等接口。dma_alloc_coherent()/dma_alloc_attrs() 等接口通过 DMA IOMMU 的回调分配内存&#xff0c;并为经过 IOMMU 的 DMA 内…

ChatGPT 上线一周年

一年前&#xff0c;ChatGPT 正式上线&#xff0c;这无疑是个革命性的时刻&#xff0c;仅仅 6 周&#xff0c;ChatGPT 用户量达到 1 个亿。 这一年元宇宙作为概念垃圾彻底进入下水道&#xff0c;而 ChatGPT 和 AI 则席卷全球。 仅仅这一年&#xff0c;依托于 ChatGPT&#xff…