史上最全IO讲解,以源码角度为你剖析,颠覆你的认知!

深入讲解Netty那些事儿之从内核角度看IO模型(上) 当我们熟悉了select的原理后,就很容易理解内核给我们提供的select API了。从select API中我们可以看到,select系统调用是在规定的超时时间内,监听(轮询)用户感兴趣的文件描述符集合上的可读,可写,异常三类事件。select传递给内核监听的文件描述符集合中数值最大的文件描述符+1,目的是用于限定内核遍历范围。select监听的文件描述符集合为,那么maxfdp1的值为5。对可读事件感兴趣的文件描述符集合。对可写事件感兴趣的文件描述符集合。对异常事件感兴趣的文件描述符集合。这里的。 阅读详情

Java IO 是一个庞大的知识体系,很多人学着学着就会学懵了,包括我在内也是如此,所以本文将会从 Java 的 BIO 开始,一步一步深入学习,引出 JDK1.4 之后出现的 NIO 技术,对比 NIO 与 BIO 的区别,然后对 NIO 中重要的三个组成部分进行讲解(缓冲区、通道、选择器),最后实现一个简易的客户端与服务器通信功能。

传统的 BIO

Java IO流是一个庞大的生态环境,其内部提供了很多不同的输入流和输出流,细分下去还有字节流和字符流,甚至还有缓冲流提高 IO 性能,转换流将字节流转换为字符流······看到这些就已经对 IO 产生恐惧了,在日常开发中少不了对文件的 IO 操作,虽然 apache 已经提供了 Commons IO 这种封装好的组件,但面对特殊场景时,我们仍需要自己去封装一个高性能的文件 IO 工具类,本文将会解析 Java IO 中涉及到的各个类,以及讲解如何正确、高效地使用它们。

BIO NIO 和 AIO 的区别

我们会以一个经典的烧开水的例子通俗地讲解它们之间的区别

类型 烧开水
BIO 一直监测着某个水壶,该水壶烧开水后再监测下一个水壶
NIO 每隔一段时间就看看所有水壶的状态,哪个水壶烧开水就去处理哪个水壶
AIO 不用监测水壶,每个水壶烧开水后都会主动通知线程说:“我的水烧开了,来处理我吧”

BIO (同步阻塞 I/O)

这里假设一个烧开水的场景,有一排水壶在烧开水,BIO的工作模式就是, 小菠萝一直看着着这个水壶,直到这个水壶烧开,才去处理下一个水壶。线程在等待水壶烧开的时间段什么都没有做。

NIO(同步非阻塞 I/O)

还拿烧开水来说,NIO的做法是小菠萝一边玩着手机,每隔一段时间就看一看每个水壶的状态,看看是否有水壶的状态发生了改变,如果某个水壶烧开了,可以先处理那个水壶,然后继续玩手机,继续隔一段时间又看看每个水壶的状态。

AIO (异步非阻塞 I/O)

小菠萝觉得每隔一段时间就去看一看水壶太费劲了,于是购买了一批烧开水时可以哔哔响的水壶,于是开始烧水后,小菠萝就直接去客厅玩手机了,水烧开时,就发出“哔哔”的响声,通知小菠萝来关掉水壶。

什么是流

知识科普:我们知道任何一个文件都是以二进制形式存在于设备中,计算机就只有 0 和 1,你能看见的东西全部都是由这两个数字组成,你看这篇文章时,这篇文章也是由01组成,只不过这些二进制串经过各种转换演变成一个个文字、一张张图片跃然屏幕上。

而流就是将这些二进制串在各种设备之间进行传输,如果你觉得有些抽象,我举个例子就会好理解一些:

下图是一张图片,它由01串组成,我们可以通过程序把一张图片拷贝到一个文件夹中,

把图片转化成二进制数据集,把数据一点一点地传递到文件夹中 , 类似于水的流动 , 这样整体的数据就是一个数据流

未命名绘图

 

IO 流读写数据的特点:

  • 顺序读写。读写数据时,大部分情况下都是按照顺序读写,读取时从文件开头的第一个字节到最后一个字节,写出时也是也如此(RandomAccessFile 可以实现随机读写)
  • 字节数组。读写数据时本质上都是对字节数组做读取和写出操作,即使是字符流,也是在字节流基础上转化为一个个字符,所以字节数组是 IO 流读写数据的本质。

流的分类

根据数据流向不同分类:输入流 和 输出流

  • 输入流:从磁盘或者其它设备中将数据输入到进程中
  • 输出流:将进程中的数据输出到磁盘或其它设备上保存

1

 

图示中的硬盘只是其中一种设备,还有非常多的设备都可以应用在IO流中,例如:打印机、硬盘、显示器、手机······

根据处理数据的基本单位不同分类:字节流 和 字符流

  • 字节流:以字节(8 bit)为单位做数据的传输
  • 字符流:以字符为单位(1字符 = 2字节)做数据的传输

字符流的本质也是通过字节流读取,Java 中的字符采用 Unicode 标准,在读取和输出的过程中,通过以字符为单位,查找对应的码表将字节转换为对应的字符。

面对字节流和字符流,很多读者都有疑惑:什么时候需要用字节流,什么时候又要用字符流?

我这里做一个简单的概括,你可以按照这个标准去使用:

字符流只针对字符数据进行传输,所以如果是文本数据,优先采用字符流传输;除此之外,其它类型的数据(图片、音频等),最好还是以字节流传输。

根据这两种不同的分类,我们就可以做出下面这个表格,里面包含了 IO 中最核心的 4 个顶层抽象类:

数据流向 / 数据类型 字节流 字符流
输入流 InputStream Reader
输出流 OutputStream Writer

现在看 IO 是不是有一些思路了,不会觉得很混乱了,我们来看这四个类下的所有成员。

image-20200823091738251

 

看到这么多的类是不是又开始觉得混乱了,不要慌,字节流和字符流下的输入流和输出流大部分都是一一对应的,有了上面的表格支撑,我们不需要再担心看见某个类会懵逼的情况了。

看到 Stream 就知道是字节流,看到 Reader / Writer 就知道是字符流。

这里还要额外补充一点:Java IO 提供了字节流转换为字符流的转换类,称为转换流。

转换流 / 数据类型 字节流与字符流之间的转换
(输入)字节流 => 字符流 InputStreamReader
(输出)字符流 => 字节流 OutputStreamWriter

注意字节流与字符流之间的转换是有严格定义的:

  • 输入流:可以将字节流 => 字符流
  • 输出流:可以将字符流 => 字节流

为什么在输入流不能字符流 => 字节流,输出流不能字节流 => 字符流?

在存储设备上,所有数据都是以字节为单位存储的,所以输入到内存时必定是以字节为单位输入,输出到存储设备时必须是以字节为单位输出,字节流才是计算机最根本的存储方式,而字符流是在字节流的基础上对数据进行转换,输出字符,但每个字符依旧是以字节为单位存储的。

节点流和处理流

在这里需要额外插入一个小节讲解节点流和处理流。

  • 节点流:节点流是真正传输数据的流对象,用于向特定的一个地方(节点)读写数据,称为节点流。例如 FileInputStream
  • 处理流:处理流是对节点流的封装,使用外层的处理流读写数据,本质上是利用节点流的功能,外层的处理流可以提供额外的功能。处理流的基类都是以 Filter 开头。

1

 

上图将 ByteArrayInputStream 封装成 DataInputStream,可以将输入的字节数组转换为对应数据类型的数据。例如希望读入int类型数据,就会以2个字节为单位转换为一个数字。

Java IO 的核心类 File

Java 提供了 File类,它指向计算机操作系统中的文件和目录,通过该类只能访问文件和目录,无法访问内容。 它内部主要提供了 3 种操作:

  • 访问文件的属性:绝对路径、相对路径、文件名······
  • 文件检测:是否文件、是否目录、文件是否存在、文件的读/写/执行权限······
  • 操作文件:创建目录、创建文件、删除文件······

上面举例的操作都是在开发中非常常用的,File 类远不止这些操作,更多的操作可以直接去 API 文档中根据需求查找。

访问文件的属性:

API 功能
String getAbsolutePath() 返回该文件处于系统中的绝对路径名
String getPath() 返回该文件的相对路径,通常与 new File() 传入的路径相同
String getName() 返回该文件的文件名

文件检测:

API 功能
boolean isFIle() 校验该路径指向是否一个文件
boolean isDirectory() 校验该路径指向是否一个目录
boolean isExist() 校验该路径指向的文件/目录是否存在
boolean canWrite() 校验该文件是否可写
boolean canRead() 校验该文件是否可读
boolean canExecute() 校验该文件/目录是否可以被执行

操作文件:

API 功能
mkdirs() 递归创建多个文件夹,路径中间有可能某些文件夹不存在
createNewFile() 创建新文件,它是一个原子操作,有两步:检查文件是否存在、创建新文件
delete() 删除文件或目录,删除目录时必须保证该目录为空

多了解一些

文件的读/写/执行权限,在 Windows 中通常表现不出来,而在 Linux 中可以很好地体现这一点,原因是 Linux 有严格的用户权限分组,不同分组下的用户对文件有不同的操作权限,所以这些方法在 Linux 下会比在 Windows 下更好理解。下图是 redis 文件夹中的一些文件的详细信息,被红框标注的是不同用户的执行权限:

  • r(Read):代表该文件可以被当前用户读,操作权限的序号是 4
  • w(Write):代表该文件可以被当前用户写,操作权限的序号是 2
  • x(Execute):该文件可以被当前用户执行,操作权限的序号是 1

image-20200825080020253

 

root root 分别代表:当前文件的所有者,当前文件所属的用户分组。Linux 下文件的

moudo网络库剖析 muduo简介 muduo是陈硕大神在Linux平台下基于C/C++开发的高性能网络库,在此基础上可以很方便的进行扩展,二次开发编写如http服务器。muduo网络库的核心框架,one thread per thread + Reactor模式。这也是大多数Linux端高性能网络编程框架应用的主要架构。 陈硕大神写的《Linux多线程服务器端编程》对muduo库整个框架和设计细节进行了非常详尽的介绍和分析,非常推荐大家阅读,不仅仅对网络编程有帮助。 此文使用muduo编写了一个简单的echoserver服 阅读详情

相关推荐

AUTOSAR/汽车行业

AUTOSAR架构及汽车产业链相关介绍

m0_54254513的博客 1万+

SSD训练自定义数据集实战:VOC格式标注与模型调参技巧

本文详细介绍了如何使用SSD模型训练自定义VOC格式数据集,包括数据标注工具选择、VOC数据集目录结构规范、数据集划分方法以及模型调参技巧。通过实战案例演示了SSD源码的关键修改点和训练参数优化策略,帮助开发者高效实现目标检测任务。

php55的博客 563

解决屏幕不亮难题:慷智SerDes DE信号极性配置避坑指南

本文深入探讨了基于慷智AIM95x系列SerDes芯片的嵌入式显示系统开发中,因DE信号极性配置不匹配导致屏幕不亮的典型故障。文章详细解析了DE信号的核心作用与极性定义,提供了慷智SerDes芯片中DE极性寄存器的具体配置方法与调试记录,并给出了从隔离问题、对比时序到波形验证的系统性排查流程,帮助工程师快速定位并解决此类隐蔽问题。

weixin_29185493的博客 141

AI 技术新手入门与实战指南

仅仅能对话还不够,实际应用中,我们往往需要让 AI 处理特定的业务数据。比如,从日志文件中提取错误码,或者将非结构化的用户反馈整理成 JSON 格式。这时候,自定义输入和严格的结果验证就显得尤为重要。假设我们需要让 AI 分析一段服务器日志,并只返回错误的级别和简述。请分析以下日志片段,提取所有 ERROR 级别的信息。要求输出格式为 JSON 列表,包含 'timestamp' 和 'message' 两个字段。不要输出任何多余的解释文字。日志内容: {

2600_94936330的博客 2681

关于Win11安装Ubuntu子系统报错:WslRegisterDistribution failed with error 解决办法

Win11安装Ubuntu子系统报错:WslRegisterDistribution failed with error

qq_51908382的博客 3万+

终于找到了!Ubuntu 虚拟机卡死的终极解决方案(如何解决VMware安装Ubuntu24.04桌面进不去、黑屏、虚拟机卡死、显示不全、屏幕闪烁等问题)

终于找到了!Ubuntu 虚拟机卡死的终极解决方案(如何解决VMware安装Ubuntu24.04桌面进不去、黑屏、虚拟机卡死、显示不全、屏幕闪烁等问题)

XiaoqiangClub的博客 1万+

TC3XX - MCAL知识点(三):MCU EB-tresos配置说明及代码浅析

AURIX 2G Tc3xx的配置相较AURIX 1G Tc2xx来讲简化了许多,但是依赖于数据手册的理解来讲整个MCU功能做了较大增强,此处先简单的介绍一下,本文前期先补充介绍一下英飞凌手册的阅读规则,因为后面的文章会基于此文的一些缩写进行截图寄存器之类的。MCU在AUTOSAR架构里面的图示如下MCU驱动程序负责配置SCU、GTM、CCU6、GPT12和STM外设。驱动程序提供由AUTOSAR指定的运行时服务。

梦想技术家 2874

Autosar MCAL-S32K324 Fee配置-基于EB

Autosar MCAL S32K324 Fee配置详解

赞的博客 1545

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版

Part-E1-SDIO-Specification-Ver4.00-Final-120220.pdf:最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版,包括SDIO 接口的外设,SDIO 接口官方协议等。

怀旧版电脑GBC模拟器

再现原版GBC掌机的界面,电脑运行连游戏界面都一样大小,很怀旧,很真实,(英文版)强烈推荐,很小的文件,很难才找到的。

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

上一篇: 死磕「并发编程」100天,全靠阿里大牛的这份最全「高并发套餐」顺利进大!
下一篇: 年薪百万大牛手写JAVA面试神器:二十五大专题,面面俱到,金九银十有保障啦!
Java领域指导者
博客等级 码龄7年 404粉丝 265原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值