初学者觉得复杂是很正常的,归根结底是因为没有理解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各种“文字”。

8,(那么,我们为什么还要学习字节流?因为字节流依然有它的作用范围。首先,所有的流都是建立在字节流之上的,比如字符流。字节流或许可以读任何字节,但是他处理不了Unicode(万国码),他处理不了Data流,Object流,也就是说,它做不了高级的事情,只能读写最原始的东西。字节流好比动物,能看,能听,能汪汪叫,但是他不能读书,不能写字,不能理解更高级的知识。其次要注意的是,字符流只能用来处理文本文件,也就是只能来处理字符,如果出来用来处理二进制文件,会带来错误,所以处理二进制文件只能用字节流)

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

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

11,讲到这里,IO流的大概思想已经说的的差不多了,是不是觉得之前混乱的那些类,现在知道他们的作用和设计思想以后,稍稍清晰了许多呢?可以简单的记,字节流是基础,理论上可用于所有的输入输出场景,内容是文字的字节流可以通过转换流转成字符流,转换流是字节流和字符流之间相互转换的桥梁,把字节流转成字符流,离不开转换流,字符流是对于字符功能的增强可用来处理“文字”,操作文件系统应用范围最广,所以JDK提供了现成的FileXXX类,用来方便编程使用。

另外,还有许多类是“在内存里自己和自己玩的”比如ByteArrayReader/Writer,PipedWriter/Reader,它们虽然也称为“流对象”但是他们的数据不出内存,所以它们的close()方法可有可无。以及其他带有某些功能的类,比如序列化流,比如数据输入输出流,等等。

IO流对象的用法和作用大同小异,其使用环境和意义取决于具体需要,用到了再具体分析即可。

这里主要介绍了JavaIO框架的设计思想,但具体底层实现细节,还需要学习JVM相关知识,以及微机原理和接口技术等等底层的课程。

手写不易,觉得文章不错可以关注公众号「 凌晨四点的程序员 」一起学习

你的关注是我分享,创作的最大动力

扫码关注送面试资料,包含技术,笔试,SQL,人事,面试指导等一大批资料,关注公众号回复"面试"即可领取
扫码关注:

为什么我觉得 Java 的 IO 很复杂?的更多相关文章

  1. java 基础题 很基础, 很有趣

    都是一些非常非常基础的题,是我最近参加各大IT公司笔试后靠记忆记下来的,经过整理献给与我一样参加各大IT校园招聘的同学们,纯考Java基础功底, 老手们就不用进来了,免得笑话我们这些未出校门的孩纸们, ...

  2. java的IO流

    java的IO流继承四大抽象类分别是字节流 inputStream outputStream与字符流 read write.怎么理解记忆很重要. 直接连接读写对象的是结点流,例如对文件读取字节类的名字 ...

  3. 【Java】IO流简单分辨

    转载请注明原文地址:http://www.cnblogs.com/ygj0930/p/5827509.html Java的IO流体系十分庞大,并且体系层次稍复杂,很容易记混或记错.在此,我把平时经常用 ...

  4. Java - 文件(IO流)

    Java - 文件 (IO)   流的分类:     > 文件流:FileInputStream | FileOutputStream | FileReader | FileWriter     ...

  5. JAVA的IO运用

    IO OF JAVA想写好一篇关于JAVA的IO的文章不容易,因为它涉及的东西很多难以写得有深度和有思路.我虽不才但也写.这篇文章有我个人不少的见解,虽然涉足计算机不深但我不想用一大堆这个可能那个可能 ...

  6. JAVA的IO学习

    IO 有具体的分类: 有具体的分类:1:根据处理的数类型不同:字节流和字符流.2:根据流向不同:输入流和输出流. =============(补充字节跟字符概念区分)================= ...

  7. 彻底明白Java的IO系统

    java学习:彻底明白Java的IO系统 文章来源:互联网 一. Input和Output1. stream代表的是任何有能力产出数据的数据源,或是任何有能力接收数据的接收源.在Java的IO中,所有 ...

  8. Java面向对象 IO (三)

     Java面向对象  IO  (三) 知识概要:                    (1)IO 流的操作规律                    (2)异常日志信息IO处理          ...

  9. Java面向对象 IO (一)

     Java面向对象  IO  (一) 知识概要:                (1)IO概述 (2)IO流的常用基类 (3)IO程序的书写 (4)字符流  写入  读取  文本文件的两种读取方式 ...

随机推荐

  1. linux-设置代理和取消代理

    设置代理: export http_proxy="http://proxy-XXXXX" export https_proxy="https://proxy-XXXXX: ...

  2. angular foreach的使用

    var myAppModule = angular.module('myApp', []); var values = { name : 'misko', gender : 'male', " ...

  3. influxes 基本概念

    Influxes 基本概念 1.安装 两种,虚机的话直接下载二进制文件起就好了,容器也很方便,存储挂载到/var/lib/influxdb 起就ok,配置文件可以通过configmap挂载进去. 2. ...

  4. 【雕爷学编程】Arduino动手做(6)---声音传感器模块

    37款传感器的提法,在网络上广泛流传,其实Arduino能够兼容的传感器模块肯定是不止37种的.鉴于本人手头积累了一些传感器,依照实践(动手试试)出真知的理念,以学习和交流为目的,这里准备逐一做做实验 ...

  5. 最香远程开发解决方案!手把手教你配置VS Code远程开发工具,工作效率提升N倍

    文章每周持续更新,原创不易,「三连」让更多人看到是对我最大的肯定.可以微信搜索公众号「 后端技术学堂 」第一时间阅读(一般比博客早更新一到两篇) 今天和大家分享远程开发工具,分享一下我平常是如何用 V ...

  6. python3.x 基础三:文件IO

    打开文件的两种方式 1.直接打开文件并赋值给变量,打开后得到操作句柄,但不会自动关闭 file = open('文件名‘,'打开模式',’编码‘) fd = open('../config/file1 ...

  7. place-holder样式

    input::-webkit-input-placeholder, textarea::-webkit-input-placeholder { color: #777; } input:-moz-pl ...

  8. 花费一周刷完两份面试pdf(含答案)轻松拿下了抖音、头条、京东、小米等大厂的offer,成功度过程序员的寒冬。

    整理出一篇Java进阶架构师之路的核心知识,同时也是面试时面试官必问的知识点,篇章也是包括了很多知识点,其中包括了有基础知识.Java集合.JVM.多线程并发.spring原理.微服务.Netty 与 ...

  9. WEB常见攻击及防御

    对于一个Web应用来说,可能会面临很多不同的攻击.下面的内容将介绍一些常见的攻击方法,以及面对这些攻击的防御手段. 一.跨站脚本攻击(XSS) 跨站脚本攻击的英文全称是Cross Site Scrip ...

  10. 面向对象案例-学生信息管理系统V0.6

    更新版本 面向对象案例 - 学生信息管理系统V1.0 项目要求: 实体类: 学生类: id, 姓名,年龄,性别,成绩 需要使用数组保存学生信息 Student[] allStu 需要完成的方法 1. ...