初学者觉得复杂是很正常的,归根结底是因为没有理解JavaIO框架的设计思想:可以沿着这条路想一想:

1,学IO流之前,我们写的程序,都是在内存里自己跟自己玩。比如,你声明个变量,创建个数组,创建个集合,写一个排序算法,模拟一个链表,使用一些常用API,现在回想一下,是不是在只是自己在内存里玩一玩?计算机组成包括运算器,控制器,存储器,输入设备,输出设备。那么你前面的工作,仅仅够你的程序和内存以及CPU打打交道,如果你需要操作外部设备呢?比如键盘,显示器,再比如,最常见的外设:硬盘?甚至未来世界里的每家每户都有的机器人,“如何让你的程序和机器人进行交互呢?”

2,所以程序设计语言必须要提供程序与外部设备交互的方式,这就是IO框架的由来。我们需要和外部设备进行数据的交互。那么,计算机是通过什么和外部进行交互的呢?很简单就能想到:数据线。数据线里传播的是什么呢?一个词:比特流。比特就是bit的谐音,计算机中“位”的意思,代表0或1。1位或者1bit,就是一个0或一个1。但是,毕竟0或1不能表示什么,所以计算机更常见的基本单位是字节,也就是用8位0或1组成的一段数据。以上是对比特流的由来做一个简单地解释。(比特流一词来自于计算机网络原理中,对物理层传输内容的描述:物理层(网线)中传输的是“比特流”,在这里借用这个名词代指数据的表示形式,帮助理解)上面两段话的意思,其实是为了下文做铺垫,帮助理解输入输出最重要的概念:方向性。输入还是输出,是相对于程序或者说相对于内存而言的。数据从外流到内存,就是输入(读),数据从内存出去,就是输出(写)。

3,既然计算机和外界进行信息的输入和输出交互,用的是比特流,那么很容易就能想到IO流名字的由来了。就是比喻输入输出的数据像流一样。我们可以这么认为,任何外部设备与内存之间输入输出的操作,都是需要输入输出流(IO流)来完成的,这里的IO流,指的就是比特流(或者称字节流)。这些外部设备,包括,键盘(标准输入设备),显示器(标准输出设备),音响,网络上另一台主机,甚至你玩游戏用的游戏手柄,以及各种各样的信号传感器,都可以叫做外部设备,和这些设备之间进行数据交互,显然不可能靠之前学习的那些数组,集合,常用类,String等等来完成。而是要靠和外界数据交换的类来完成。靠什么来进行数据交换,就是前面说的,比特流,或者说IO流类。

4,那么,既然要学习IO流,就得针对某一个输入输出设备来学习。哪种输入输出设备最重要同时也最常见?当然是硬盘。硬盘在这里的含义也可以理解为文件系统。(Java程序是运行在某操作系统平台上的应用软件JVM上的,实际上Java程序可见的并不是硬盘,而是操作系统提供的文件系统,因此此处可直接理解为文件系统)。因此,我们学习IO流的时候,基本上是学习的Java如何操作文件系统,除了文件系统,我们还能够了解Java操作标准输入输出设备,如http://System.in和System.out。

5,知道了学习的方向,是要使用Java操作文件系统,那么首先要学习的就是文件的表示,即File类。然后,我们要操作做文件,虽然我们大部分操作都是操作文件系统,但是要明白IO流的概念不仅仅局限在操作文件上,前面我已经提到了,我们的编程语言是要能操作所有的输入输出,因此,API提供了两个顶层抽象类,用来表示操作所有的输出输出:InputStream,OutputStream。并且,这两个类表示字节的输入输出,因为输入输出的本质是字节流。这里注意体会一句话“字节流是最最基本的流”,这句话的由来就是因为计算机底层传递的就是字节。那么,当我们要操作文件的时候,就需要具体的对文件系统操作的IO实现类,于是我们需要学习FileInputStream和FileOutputStream,它们是文件输入输出字节流。这里之所以FileInputStream/OutputStream作为子类出现,按照面向对象思想理解就是,将来还有别的字节流来操作别的设备(比如将来需要通过操作网络设备获取网络数据,再比如需要操作机器人,那么或许就会再来个RobotInputStream和RobotOutputStream,这些新的需求也就都可以继承这个体系)(这里顺便提一句架构设计思想,其中有一种设计原则叫“开闭原则”,其核心是:一个对象对扩展开放,对修改关闭。就是说,一旦写好了某个类,就不要去轻易改动他,而是要保证它一直能运行下去,而面对新的功能需求时,只要在原有代码上增加即可,而不是修改原有代码。要做到开闭原则,就需要分清需求中未来哪些部分是稳定的,哪些是很可能变化的,而往往抽象的部分是最稳定的,把稳定的内容分离出来,就能满足开闭原则。这就是为什么Java的类设计的如此之琐碎,为什么我们要从继承关系角度去理解JavaIO流的设计)

6,学了文件IO字节流之后,我们会发现原始的字节流对象用起来没那么高效,因为每个读或写请求都由底层操作系统处理,这些请求往往会触发磁盘访问、网络活动或其他一些相对昂贵的操作。不带缓冲区的流对象,只能一个字节一个字节的读,每次都调用底层的操作系统API,非常低效,而带缓冲区的流对象,可以一次读一个缓冲区,缓冲区空了才去调用一次底层API,这就能大大提高效率。所以又有了BufferedInputStream和BufferedOutputSteam,他们的用法是把字节流对象传入后再使用,也相当于把它俩套在了字节流的外面,给字节流装了个“外挂”,让基本字节流如虎添翼。

7,说到操作文件,就不得不提到文件的分类和编码格式。文件分为二进制文件和文本文件,二进制文件是用记事本打开后看不懂的,他们的编码格式是特殊的,比如pdf文件,exe文件。记事本打开后人能看懂的只有纯文本文件,我们处理文件(或者说处理任何的字节流),就免不了处理一些文本文件(或文本字节流)。如果是英语国家的人还好说,因为他们是用的常用字符用一张ASCII码表就能表示得出来,用一个字节就能表示一个字母。但是显然,对非英语国家的人来说,一个字节的大小无法表示他们所有的文字。因此,人们需要有能够处理字符的类,或者说这个类提供一个功能:就是把输入的字节转成字符,把要输出的字符转成计算机可以识别的字节。所以,你需要两个转换流:InputStreamReader和OutputStreamWriter。这两个类的作用分别是把字节流转成字符流,把字符流转成字节流。但是这两个流需要套在现成的字节流上才能使用,当中用到的设计模式也就是常说的装饰模式。当字节流被转成字符流之后,恭喜你,你可以不必操作字节流了,而是可以用人类的方式read和write各种“文字”。(那么,我们为什么还要学习字节流?因为字节流依然有它的作用范围。首先,所有的流都是建立在字节流之上的,比如字符流。字节流或许可以读任何字节,但是他处理不了Unicode(万国码),他处理不了Data流,Object流,也就是说,它做不了高级的事情,只能读写最原始的东西。字节流好比动物,能看,能听,能汪汪叫,但是他不能读书,不能写字,不能理解更高级的知识。其次要注意的是,字符流只能用来处理文本文件,也就是只能来处理字符,如果出来用来处理二进制文件,会带来错误,所以处理二进制文件只能用字节流)

8,还是回到文件系统,我们最常见的是和文件系统打交道,那么针对如此常见的用途,读取文本文件能不能用一种方便的方式呢?当然,大牛们替你想到并提供了。FileReader和FileWriter这两个流对象可以直接把文件转成读取、写入流。让你省去了创建字节流,再套上转换流的步骤。看看这类名起的,实际上很形象,xxxReader和xxxWriter,明摆着告诉你“阅读和书写”都是“人可以做的”也就是他们表示的是字符流。同理上面的InputStreamReader和OutputStreamWriter,表示的是把字节流转成人可读的,把字节流转成人可写的。因此他们的顶层抽象类:Reader和Writer,表示的是所有人类可读可写的字符流统称。

9,同上面说的缓冲区的作用,再把Reader和Writer做成高效的,就需要BufferedReader和BufferedWriter,把它们套在Reader和Writer上,就能实现高效的字符流。

10,讲到这里,IO流的大概思想已经说的的差不多了,是不是觉得之前混乱的那些类,现在知道他们的作用和设计思想以后,稍稍清晰了许多呢?可以简单的记,字节流是基础,理论上可用于所有的输入输出场景,内容是文字的字节流可以通过转换流转成字符流,转换流是字节流和字符流之间相互转换的桥梁,把字节流转成字符流,离不开转换流,字符流是对于字符功能的增强可用来处理“文字”,操作文件系统应用范围最广,所以JDK提供了现成的FileXXX类,用来方便编程使用。另外,还有许多类是“在内存里自己和自己玩的”比如ByteArrayReader/Writer,PipedWriter/Reader,它们虽然也称为“流对象”但是他们的数据不出内存,所以它们的close()方法可有可无。以及其他带有某些功能的类,比如序列化流,比如数据输入输出流,等等。IO流对象的用法和作用大同小异,其使用环境和意义取决于具体需要,用到了再具体分析即可。这里先写到这了。这里作为Java编程入门应该可以了,主要介绍了JavaIO框架的设计思想,但具体底层实现细节,还需要学习JVM相关知识,以及微机原理和接口技术等等底层的课程。

转:https://www.zhihu.com/question/67535292/answer/1248887503

如何学IO流IO流的含义相关推荐

  1. java 的io流需要学吗_Java Io流怎么学习呢?

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

  2. 学Java基础19 字符流 编码表 转换流 字符高效流 对象流 序列化 以及所有的IO流总结

    一.字符流概述 1.字符流 就是用于来读写字符操作的流 2.字符流使用的原因: 使用字节流来读取文件中中文会出现乱码 因为中文不是一个字节组成的 所以读取中文的时候 需要使用字符流 字符实际上也是使用 ...

  3. 【小白学Java】D32》》》IO流 之 序列化流 打印流

    [友情链接]➡➡▶IO流 之 File类 & 递归 [友情链接]➡➡▶IO流 之 过滤器 & 字节流 [友情链接]➡➡▶IO流 之字符流 & 属性集(Properties集合) ...

  4. JAVA语言基础-面向对象(IO:IO字符流、递归)

    2019独角兽企业重金招聘Python工程师标准>>> 21.01_IO流(字符流FileReader) 1.字符流是什么 字符流是可以直接读写字符的IO流 字符流读取字符, 就要先 ...

  5. IO流的字符流+对象流+打印流+内存流+随机访问流(2)

    IO流的字符流+对象流+打印流+内存流+随机访问流(2) 一.字符流 1.利用字符输出转换流 向文件写入数据 1.文件存在的情况 2.文件不存在的情况 经验:所有的输出流,当文件不存在时都会创建文件 ...

  6. IO流 字符流 字节流 缓冲流 文件的复制

    IO流 IO概述 IO流就是一个管道,是用来在设备之间传输数据 input:相对于内存/程序 往进走输入流 output:相对于内存/程序 往硬盘写入 分类 根据数据进出方式 1.输出流: FileW ...

  7. Java基础学习总结(13)——流IO

    2019独角兽企业重金招聘Python工程师标准>>> 一.JAVA流式输入/输出原理 流是用来读写数据的,java有一个类叫File,它封装的是文件的文件名,只是内存里面的一个对象 ...

  8. Java基础知识强化之IO流笔记41:字符流缓冲流之复制文本文件案例02(使用 [ newLine() / readLine() ] )(重要)...

    1. 使用字符流缓冲流的特殊功能 [ newLine() / readLine() ] 需求:把当前项目目录下的a.txt内容复制到当前项目目录下的b.txt中  数据源: a.txt -- 读取数据 ...

  9. IO流(IO异常处理方式)

    IO流(IO异常处理方式) 参考文章: (1)IO流(IO异常处理方式) (2)https://www.cnblogs.com/yangyongqian/p/5150838.html 备忘一下.

最新文章

  1. Libgdx学习笔记:分享自己写的异步加载
  2. 大幅涨点!孙剑团队提出新激活层ACON和轻量级网络TFNet
  3. dede php 常用,dede cms常用标签汇总 收藏版
  4. python 链表的反转
  5. 中央财经大学计算机专业排名,中央财经大学怎么样 2021年全国排名多少
  6. 《极乐迪斯科》:一趟充满新奇的旅程 ,一款里程碑式的 CRPG
  7. javascript OOP 面向对象编程
  8. java 文件上传至oracle blob字段 实现
  9. 通过socket得到远端的IP和连接端口
  10. 如何进阶一名有竞争力的程序员? 1
  11. python 绘图中文显示_Python绘图实现显示中文
  12. 数据压缩作业一:音频时域频域特性分析(Audacity)及RGB文件熵的计算
  13. CentOS7安装杀毒软件ClamAV图形界面ClamTk
  14. P1757 通天之分组背包题解
  15. 公司股权外部转让流程
  16. (修订)斩获腾讯微信后台开发offer大神的近1.5W字的面试干货分享
  17. 【SQL】CAST()函数,(CAST AS decimal)
  18. 龙族幻想东京机器人一次_龙族幻想凌晨四点的东京机器人坐标-机器人刷新点_6137游戏网...
  19. 跟着大佬上大分-Web of Lies
  20. 机原、机设的主干知识_简要复习笔记

热门文章

  1. c++初学基础小知识
  2. 微信链接修改图片_微信链接修改图标
  3. Hbase Coprocessor(协处理器)的使用
  4. 威廉•欧奈尔选股七法
  5. [ 大数据分析 ] 大数据分析与处理方法介绍
  6. 时钟周期、机器周期、总线周期、指令周期的关系
  7. 完全背包与01背包的区别
  8. js对象转数组可枚举属性和不可枚举属性
  9. 编译器,解释器,预编译器之间的关系
  10. 根据日期计算属于第几周(周日是一周的第一天)