从零开始学Java之IO流到底是怎么回事?

2023年 9月 4日 66.3k 0

作者:孙玉昌,昵称【一一哥】,另外【壹壹哥】也是我哦

千锋教育高级教研员、CSDN博客专家、万粉博主、阿里云专家博主、掘金优质作者

前言

经过前面一系列内容的学习,壹哥相信大家现在已经具备了比较扎实的Java基础了,很多小白也从小班进入到了大班,所以接下来我们就可以学习一些稍微复杂点的知识了。

请注意,前方高能!前方高能!前方高能! 接下来请各位备好晕车药,老司机要飙车了,壹哥这就开始带你学习Java中特别容易让小白头大蒙圈的IO流!

之所以说IO流很让小白头大,主要是因为IO流的内容实在太多了,一会是输入流,一会是输出流,还有字节流、字符流、文件输入流,文件输出流,缓冲流.....呜呜泱泱一大堆。光是IO流中的英文单词都把人看的脑袋都大了,并且很多API的名字又较长又相似,这对初学者来说都是学习中的难点。

但我们在开发时用到IO流的地方确实有很多,比如文件的上传下载,数据传输、存储,音视频编解码等重要操作,另外面试官也很喜欢考察我们对IO流的掌握是否扎实。所以这就需要各位在阅读接下来的几篇文章时,务必打起精神,熬过这个难受的阶段,守得云开见月明哦。

------------------------------前戏已做完,精彩即开始----------------------------

全文大约【4200】 字,不说废话,只讲可以让你学到技术、明白原理的纯干货!本文带有丰富的案例及配图视频,让你更好地理解和运用文中的技术概念,并可以给你带来具有足够启迪的思考......

配套开源项目资料

Github: github.com/SunLtd/Lear…

Gitee: 一一哥/从零开始学Java

我们首先要搞清楚一件事,就是为什么需要IO流这个东西。

我们知道,你可以把数据保存在变量、数组、集合等结构中,但这些结构都是在内存中存储的,里面的数据都是暂时存在的,一旦程序结束这些数据就会消失。所以为了能够永久地保存数据,我们就需要把数据存储到磁盘和文件中,这样就可以长期的使用了。要想把数据从内存中读取写入到磁盘中,这就需要使用IO(输入/输出)流技术了。

但在正式学习IO流的使用之前,壹哥有必要带大家先了解一下IO流的基本概念。

一. IO流概念

首先壹哥给大家来解释一下 “IO流” 这个概念,如果我们连 IO流 是个啥都不知道,也就没必要继续往下看了。在这里壹哥会从两部分展开介绍IO流,即 “IO” 与 “流” 。

1. IO

IO其实代表的是两个内容,即 “I” 与 “O”,它们分别是 “In” 与 “Out” 的缩写。

In:输入, 代表着能够接收数据的数据源对象,从外部设备把数据输入到内存;

Out:输出, 代表着能够产出数据的数据源对象,从内存中输出数据到外部设备。

对我们来说,大家只需要记住,输入与输出都是以内存为参照物的即可!

2. 流

接下来咱们再来看看什么是 “流”!请先在脑海里想一下,“流”是一种什么样的形态?其实Java中各个API的命名都是很形象的,绝对都做到了见名知意,这里的“流”就是一个很形象的概念!可以说,流是一组有序的数据序列,能把数据从一个地方带到另一个地方。根据数据流向的不同,可以分为输入(Input)流和输出(Output)流两种。

  • 输入流:当我们的代码程序需要 读入数据 的时候,可以开启一个连通 数据源 ****的流(输入流) ,这个数据源可以是文件、内存、数据库,或是网络连接。
  • 输出流:同样的,当我们的代码程序需要 输出数据 的时候,也可以开启一个连通 目的地 ****的流(输出流), 这个目的地一般是指我们的代码程序。

你可以想象一下,我们的数据好像就是在数据源与目的地之间 “流动” 了起来。其实 流(stream)这个概念,一开始源于UNIX中的管道(pipe)概念 。 在UNIX中,管道是一条不间断的字节流,用来实现程序或进程间的通信,或读写外围设备、外部文件等。最后壹哥再给各位提取一下流的概念:

流是一组有顺序的,有起点和终点的字节集合,是对数据传输的总称或抽象。数据在两设备间的传输称为流,流的本质是数据传输,根据数据传输的特性可以将流抽象为各种类,方便更直观的进行数据操作。

3. IO流

最后,我们再把IO流的概念梳理一下。

程序中的数据需要移动传输,比如硬盘上的数据需要出现在显示器上,从键盘输入的内容需要存储在硬盘上,所有的这些操作都要进行数据传输,而在Java中负责进行数据传输的技术就是“IO流”。这是一种按顺序读写数据的模式,它的特点是单向流动,数据会像自来水一样在水管中流动,所以我们把它称为IO流。

外部的数据输入到计算机,计算机内部的数据输出到外部,这个实现的过程就是由IO流来完成的,且输入和输出都是以内存为中心的。

  • Input输入:是把数据从各种外部的输入设备(键盘、麦克风等)中读入到内存,例如,把文件从硬盘读取到内存,从网络读取数据到内存等;
  • Output输出:指把数据从内存输出到各种外部设备(如显示器、磁盘等),例如,把数据从内存写入到文件,把数据从内存输出到网络等。

我们之所以要以内存为中心,是因为代码要运行在内存中,这就需要各种数据都必须进入到内存中进行处理。大家要注意,IO流对数据的处理,只能按照数据序列的顺序来进行,即前一个数据处理完之后才能处理后一个数据,否则会产生异常。

二. 作用

那么根据上面壹哥对IO流的描述,我们就可以搞清楚出IO流的核心作用,如下:

IO流可以在数据源和目的地之间搭建一个传输通道,用于处理设备与代码程序之间的数据传输,设备是指硬盘、内存、数据库、键盘录入、网络等。

一言以蔽之,IO流屏蔽了实际的设备处理数据细节,我们不必关心其内部具体的流动过程,只需知道IO流是用来处理设备之间数据传输的即可。

三. 分类

如果你只看上面IO流的概念,感觉也没有什么难度,但是关于IO流的学习,最难的是分类太多。IO流有着不同的划分维度,如果我们根据这些不同的标准来分类的话,可以分类如下:

  • 按IO流的流动方向分为: 输入流和输出流;
  • 按IO流的数据单位分为: 字节流和字符流;
  • 按IO流的不同功能分为: 节点流和处理流。

接下来 壹哥 会分别解释一下这几种类型。

1. 输入流与输出流

从IO流的流动方向上,我们知道IO流可以分为输入流与输出流,但不少初学者总是分不清输入流与输出流,甚至会把两者搞反。所以接下来 壹哥 就再明确一下输入流与输出流的区别,我们来看下图:

在上图中,我们以家中自来水的进水与出水来形象的比喻输入流与输出流。

  • 自来水公司相当于是数据源,我们家中的房子就相当于是目的地;
  • 自来水公司的水进入到我们家里,这就是自来水的输入;
  • 我们家中产生的污水,要排到污水处理厂,这就是自来水的输出。

在这个供水、排水的过程中,我们可以想一下,输入、输出是不是一个相对的概念呢?那么相对于哪个角色呢?没错!输入、输出都是相对于我们的房子来说的,进入到房子叫做输入,从房子流出就叫做输出。所以房子就是输入和输出的参照物,这就和内存是IO流的输入、输出参照物一样!

最后,壹哥 再把上图中的各角色明确一下:

  • 数据源: 上图中自来水公司的水池,用于提供自来水(数据);
  • 输入流: 从自来水公司进到房子里的管道,携带着具体的数据家里来;
  • 目的地: 上图中的房子,这代表着我们项目的代码程序,或者说是内存;
  • 输出流: 从家中流出到污水厂的管道流,携带着具体的数据到污水厂;
  • 数据目标: 最后的污水厂,这是用于持久化存储污水(数据)的地方,其实也是一种数据源。

所以,IO流中的输入流与输出流,入与出都是相对于内存而言的。从某个数据源读取数据到内存中,被称为输入流;从内存中把数据持久化保存到其他设备上,则被称为输出流。简单一句话,流向内存是输入流,流出内存的输出流。 我们再来看下图:

另外要注意,我们可以从输入流中读取信息,但不能对它写;可以对输出流进行写操作,但不能对其读。所以输入也叫做读取数据,输出也叫做作写出数据!

至此,你应该不会再把输入流和输出流搞反了吧,是不是应该给 壹哥 点个赞呢,hiahia......

2. 字节流与字符流

上面 壹哥 说了,按照数据流的数据单位不同,可以把IO流分为字节流与字符流,两者的区别如下:

  • 字节流: 字节流是以字节(8bit)为单位进行数据的按序传输,一次读取或写入一个字节(8位)的二进制数据, 字节流能处理所有类型的数据(如图片、音频、视频等) ;
  • 字符流: 字符流以字符为单位进行数据的按序传输,根据码表映射字符,一次读取或写入一个字符(可能是多个字节),一次读入或写出16位二进制数据, 字符流只能处理文本文件中的字符类型数据 。

字节流和字符流的这些区别,主要是因为Java一个字节的空间是1个Byte,即8位;而一个字符的空间是2个Byte,即16位。另外Java的字节是有符号类型,字符是无符号类型!

另外我们还知道,计算机中的一切文件数据(文本、图片、视频等)在存储时,都是以二进制的形式保存的,即都是一个一个的字节,在传输时也同样如此。所以,字节流可以传输任意类型的文件数据。在操作流的时候,我们要时刻明确,无论使用什么样的流,底层传输的始终为二进制数据。

但如果我们需要读写的内容是字符,并且字符不全是单字节表示的ASCII字符。有很多的字符是用Unicode编码表示的,采用的是双字节,而InputerStream是用来处理单字节的,在处理字符文本时不是很方便,所以就需要有一种可以高效处理字符的流。字符流的本质其实也是基于字节流的,所以字节流和字符流的原理其实也是相同的,只不过处理的数据单位大小不同而已。一般情况下,Java所有关于IO流的API,后缀是Stream的是字节流,后缀是Reader和Writer的是字符流。但你可能会问,我们在开发时,到底是要选择字节流还是字符流呢?

答案就是,对于字节流和字符流,如果我们只是想处理纯文本数据,可以优先考虑字符流,除此之外尽量使用字节流。

3. 节点流与处理流

另外如果从IO流的功能角度来看,IO流可以分为节点流和处理流,两者有以下区别。

节点流,可以直接与数据源相连,进行读入或写出。

但如果我们直接使用节点流进行操作,读写并不方便,所以为了更快的读写文件,就有了处理流。

处理流,一般会与节点流一起使用,在节点流的基础上,再套接一层,套接在节点流上的就是处理流。

四. 使用场景

总之,Java中有种类丰富且功能强大的IO流机制,包含了多种流类型,例如:字节流、字符流、缓冲流、数据流、对象流等。我们利用这些流,可以进行文件读写、网络传输、图片处理、音频视频处理等场景。

------------------------------正片已结束,来根事后烟----------------------------

五. 结语

至此,壹哥就在今天的这篇文章中给大家科普了IO流的基本概念,今天的重点如下:

  • IO流是一种流式的数据输入/输出模型,负责在数据源和目的地之间搭建一个传输通道,用于处理设备与代码程序之间的数据传输;
  • 输入与输出都是针对内存而言的;
  • 字节流是以字节(8bit)为单位进行数据的按序传输,一次读取或写入一个字节(8位)的二进制数据;
  • 字符流以字符为单位进行数据的按序传输,根据码表映射字符,一次读取或写入一个字符(可能是多个字节)。

在下一篇文章中,壹哥会给大家介绍IO流相关的API类,敬请继续关注哦。另外如果你独自学习觉得有很多困难,可以加入壹哥的学习互助群,大家一起交流学习。

相关文章

JavaScript2024新功能:Object.groupBy、正则表达式v标志
PHP trim 函数对多字节字符的使用和限制
新函数 json_validate() 、randomizer 类扩展…20 个PHP 8.3 新特性全面解析
使用HTMX为WordPress增效:如何在不使用复杂框架的情况下增强平台功能
为React 19做准备:WordPress 6.6用户指南
如何删除WordPress中的所有评论

发布评论