• 深入理解:输入流read()方法的底层运作原理,以及为什么缓存空间可以极大的提升IO流读写文件的效率


    深入理解:输入流read方法的底层运作原理,以及为什么缓存空间可以极大的提升读取文件的效率

    一·FileInputStream类的read方法官方JDK解释如下图所示:可能文档说的太过官方,本人来阐述说明一下。

    在这里插入图片描述

    1.read():

    在这里插入图片描述

    (1)当输入流对象调用这个方法时,一次调用只会从某个文件中读取一字节(也就是8位)的二进制数据,然后返回读取的一字节数据。
    
    (2)执行完一次调用之后,该方法并不会立即停掉,而是会进入阻塞状态。进程阻塞就是进程会在后台挂起,即,占着cpu内存,却不执行任何任务,但这样可以加快启动与调用的速度。
    一旦这样的进程过多就会很耗费计算机各种资源,所以每次我们读完文件数据之后,都必须关掉输入输出流的原因就是这么回事。
    
    (3)直到利用“同一个输入流对象”再次调用它,那么该read方法就会被唤醒,它就会接着从上次停止的地方继续执行读取操作。
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    2.read(byte [] b ):开发中常用

    在这里插入图片描述

    (1)当输入流对象调用这个方法时,该方法底层会一字节一字节的读取数据,每读取到一字节数据就会自动填充到缓存数组byte[]中去(从数组偏移量0开始),
    直到填满缓存数组,该read方法就会返回本次调用填充缓存数组的总字节数。
    
    (2)执行完一次调用之后,该方法并不会立即停掉,而是会进入阻塞状态。进程阻塞就是进程会在后台挂起,即,占着cpu内存,却不执行任何任务,但这样可以加快启动与调用的速度。
    一旦这样的进程过多就会很耗费计算机各种资源,所以每次我们读完文件数据之后,都必须关掉输入输出流的原因就是这么回事。
    
    (3)一般循环调用该方法读取文件数据时,不到文件末尾,每次读取的总字节数都会与缓存数组长度相等。
    也就是说倒数第三次以上读取的文件总字节数,
    都等于缓存数组长度;但是倒数第二次读取的总字节数就不一定等于缓存数组的长度,因为文件未被读取数据已经没了;
    最后一次读取返回的才是-1,表示读取文件数据截止。
    
    (4)直到利用“同一个输入流对象”再次调用它,那么该read方法就会被唤醒,它就会接着从上次停止的地方继续执行读取操作。
    
    (5)注意:若最后一次调用该方法去读取文件的数据不够填满缓存数组,那么则会返回实际填充缓存数组的总字节数并进入阻塞状态;此时,再次调用该read方法,返回的才是-1,表示文件末尾截止了!!!
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    3.read( byte [] b , int off , int len):

    在这里插入图片描述

    (1)当输入流对象调用这个方法时,该方法底层会一字节一字节的读取数据,每读取到一字节数据就会自动填充到缓存数组byte[]中去(从数组偏移量off开始),
    一次方法调用中最多填充len字节数到缓存数组中,该read方法就会返回本次调用填充缓存数组的总字节数。
    
    (2)执行完一次调用之后,该方法并不会立即停掉,而是会进入阻塞状态。进程阻塞就是进程会在后台挂起,即,占着cpu内存,却不执行任何任务,但这样可以加快启动与调用的速度。
    一旦这样的进程过多就会很耗费计算机各种资源,所以每次我们读完文件数据之后,都必须关掉输入输出流的原因就是这么回事。
    
    (3)直到利用“同一个输入流对象”再次调用它,那么该read方法就会被唤醒,它就会接着从上次停止的地方继续执行读取操作。
    
    (4)如果off为负数,或者len为负数,也或者 len为大于 b.length - off 的数,这个方法运行时都会报错
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    二·FileReader类都是继承实现的Reader基类的read方法,官方JDK解释如下图所示:可能文档说的太过官方,本人来阐述说明一下。

    在这里插入图片描述

    1.read():

    在这里插入图片描述

    (1)当输入流对象调用这个方法时,一次调用只会从某个文件中读取一字符的二进制数据,然后返回读取的一字符数据。
    注意:若字符是英文,则是读取一字节的数据;若字符是汉字,则是读取2字节的数据;返回的是二进制数据,显示在控制台会转换为int类型数据,只要将这个int类型数据赋值给char类型数据再进行输出就可以成功转换为字符了。
    
    (2)执行完一次调用之后,该方法并不会立即停掉,而是会进入阻塞状态。进程阻塞就是进程会在后台挂起,即,占着cpu内存,却不执行任何任务,但这样可以加快启动与调用的速度。
    一旦这样的进程过多就会很耗费计算机各种资源,所以每次我们读完文件数据之后,都必须关掉输入输出流的原因就是这么回事。
    
    (3)直到利用“同一个输入流对象”再次调用它,那么该read方法就会被唤醒,它就会接着从上次停止的地方继续执行读取操作。
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    2.read​(char[] cbuf):开发中常用

    在这里插入图片描述

    (1)当输入流对象调用这个方法时,该方法底层会一字符一字符的读取数据,每读取到一字符数据就会自动填充到缓存数组char[]中去(从数组偏移量0开始),
    直到填满缓存数组,该read方法就会返回本次调用填充缓存数组的总字符数。
    
    (2)执行完一次调用之后,该方法并不会立即停掉,而是会进入阻塞状态。进程阻塞就是进程会在后台挂起,即,占着cpu内存,却不执行任何任务,但这样可以加快启动与调用的速度。
    一旦这样的进程过多就会很耗费计算机各种资源,所以每次我们读完文件数据之后,都必须关掉输入输出流的原因就是这么回事。
    
    (3)一般循环调用该方法读取文件数据时,不到文件末尾,每次读取的总字符数都会与缓存数组长度相等。
    也就是说倒数第三次以上读取的文件总字符数,都等于缓存数组长度;
    但是倒数第二次读取的总字符数就不一定等于缓存数组的长度,因为文件未被读取数据已经没了;最后一次读取返回的才是-1,表示读取文件数据截止。
    
    (4)直到利用“同一个输入流对象”再次调用它,那么该read方法就会被唤醒,它就会接着从上次停止的地方继续执行读取操作。
    
    (5)注意:若最后一次调用该方法去读取文件的数据不够填满缓存数组,那么则会返回实际填充缓存数组的总字符数并进入阻塞状态;此时,再次调用该read方法,返回的才是-1,表示文件末尾截止了!!!
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    3.read​(char[] cbuf, int off, int len):

    在这里插入图片描述

    (1)当输入流对象调用这个方法时,该方法底层会一字符一字符的读取数据,每读取到一字符数据就会自动填充到缓存数组char[]中去(从数组偏移量off开始),
    一次方法调用中最多填充len字符数到缓存数组中,该read方法就会返回本次调用填充缓存数组的总字符数。
    
    (2)执行完一次调用之后,该方法并不会立即停掉,而是会进入阻塞状态。进程阻塞就是进程会在后台挂起,即,占着cpu内存,却不执行任何任务,但这样可以加快启动与调用的速度。
    一旦这样的进程过多就会很耗费计算机各种资源,所以每次我们读完文件数据之后,都必须关掉输入输出流的原因就是这么回事。
    
    (3)直到利用“同一个输入流对象”再次调用它,那么该read方法就会被唤醒,它就会接着从上次停止的地方继续执行读取操作。
    
    (4)如果off为负数,或者len为负数,也或者 len为大于 b.length - off 的数,这个方法运行时都会报错
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    三·为什么缓存空间可以极大的提升IO流读写文件的效率,又是如何提升系统的整体性能呢?

    1.前提共识:不需要修改原文件数据的操作就是输入流,需要修改某文件数据的操作就是输出流。

    (1)从磁盘往cpu内存读取数据的速度为v1
    (2)从cpu内存往程序里面读取数据的速度为v2
    (3)从程序里面往cpu内存写数据的速度为v3
    (4)从cpu内存往磁盘写数据为v4

    结论:v2 = v3,v1 = v4,v2 >> v1,v3 >> v4

    2.缓存空间节省IO流操作文件时间的过程,可以通过一个比较直观形象的比喻来阐述说明,如下图所示:在文件大小不变的情况下,缓存空间就相当于提升了读写文件的效率。

    在这里插入图片描述

    3.输出流一次写出一个字节数据,与一次写出很多个字节数据,耗费的时间几乎相差不大。

    四·注意事项:

    1.缓存数组,又称“缓冲数组”

    2.官方文档中“直到某些输入可用”的词语解释:直到利用同一个输入流对象再次调用该read方法

    3.调用read(byte[] b)以及read( byte [] b , int off , int len)方法时,传入的缓存字节数组byte[]大小,可以随便设置长度,但长度不能小于1。

    4.缓冲数组可以极大的提升IO流读写文件的效率,当很多缓存空间都发挥如此作用的时候,也就提升了系统的整体性能。

    5.当read方法读取数据返回的是-1时,此时read方法虽然会停掉,但是输入流进程仍然没有关闭,必须执行close方法才能关闭流的进程。

    6.其他输入流的read方法理解本质上与上文两种都差不多,类推就行

  • 相关阅读:
    学习c#的第十九天
    STC 32位8051单片机开发实例教程 一 开发环境搭建
    CMakeList.txt
    再说Mdx的字典文件处理
    otomegame游戏音频提取通用教程
    vue2 判断当前设备是移动端还是PC端
    通过自学可以搭建量化交易模型吗?
    私网环境下如何使用云效流水线进行 CI/CD?
    聚类分析、matlab\我国各地区普通高等教育发展状况分析、Q型、R型聚类
    VLAN间路由课堂总结及园区网组网实验
  • 原文地址:https://blog.csdn.net/weixin_48033662/article/details/125897980