【Java】基础41:什么叫IO流?

一、IO流概述

说到IO流,先得提一提电脑的基本概念:

  • CPU:*处理器,处理速度最快。

  • memory:内存,临时性存储设备,处理速度次之,但数据不保存。

  • disk:硬盘,持久性存储设备,处理速度最慢,但数据永久保存。

什么叫IO流?

IO流,就是指读写文件的技术。

1.input

I就是指input:输入的意思,这是输入流。

意思是将硬盘里的数据输入到内存里,也就是读取文件。

2.output

O指output:输出的意思,这是输出流。

意思是将内存中的数据输出到硬盘上,也就是写入文件。

用一句话记忆就是:输入到内存(读取硬盘),从内存输出(写入硬盘)

举一个例子:

我们在记事本上写东西,写完后保存,保存的过程就是写入文件的过程。

  • 不保存:数据是在内存里面,退出后数据会消失;
  • 保存:数据会被写到硬盘上,退出后数据也会保存。

其中根据数据的类型IO流又分为:

字节流 :以字节为单位读写数据的流,能够操作所有文件

  • 字节输入流: InputStream
  • 字节输出流: OutputStream

字符流 :以字符为单位读写数据的流,用于操作文本文件

  • 字符输入流: Reader
  • 字符输出流: Writer

今天主要讲讲字节流:

二、OutputStream输出流

它是输出流最上层的父类,是一个抽象类,其中它有一个子类叫FileOutputStream。

1.构造方法(一)

先介绍其两个构造方法:

【Java】基础41:什么叫IO流?

①构造方法一:路径存在

FileOutputStream(String name)。

根据文件路径输出文件,“a.txt”是一个相对路径,所以是输出在当前项目下。

②构造方法一:路径不存在

“aa/a.txt”因为其父路径不存在,所以会报错。

③构造方法二

FileOutputStream(File file)。

一般都是使用构造方法一,简单方法,只要输入路径就好了,但是会出现②中的这种情况。

而构造方法二就是解决这类问题的。

可以先在file中加一个判断,父路径不存在就先创建目录,再创建输出流。

2.常用方法

【Java】基础41:什么叫IO流?

①write(int b)方法

这个方法表示是一个字节一个字节地写。

按照ASCII码表编码,97就对应a,98就对应b,99就对应c。

所以①的操作会在文件里写入abc。

②write(byte[] b)方法

这是先写一个byte数组,在写入文件。

也是按照ASCII码表编码。

③write(byte[] b, int off, int len)

off表示的是偏移量

len表示的是长度

也就是说写入文件的数组,是从b数组中off索引位开始,2个长度。

④close()方法

关流,节省资源。就可以将其理解成关闭水龙头。

所以在a.txt文件中会写入:abcabcbc。

3.构造方法(二)

【Java】基础41:什么叫IO流?
我们新创建一个输出流,操作同一个文件,写入一个数组,会将文件中的内容覆盖掉。

a.txt文件里的内容从abcabcbc变成了刘小爱。

但若是我不是想覆盖而是续写在后面该怎么办?

构造方法三:

FileOutputStream(String name,boolean append)

append,附加的意思,默认值为false。

  • 如果append为true的话,会拼接到文件后面;
  • 如果append为false的话,就会覆盖。
    【Java】基础41:什么叫IO流?
    ①直接输入换行符

不同的操作系统有着不同的换行符

  1. Windows 系统识别的换行符:\r\n
  2. Unix 系统识别的换行符:\n
  3. MacOs/Linux系统识别的换行符:\r

②System方法输入换行符

System.lineSeparator():该方法会根据系统的不同而输入不同的换行符。

三、InputStream输入流

它是输入流最上层的父类,是一个抽象类,其中它有一个子类叫FileInputStream。

1.read方法基本用法
【Java】基础41:什么叫IO流?

①创建输入流

如果文件不存在,输入流会直接报错。

②read()方法

输入流的读操作。

  • 返回值即为读取的字符,一次只能读取一个;
  • 如果读到了文件末尾,返回值为-1。

③使用while循环

一次读取所有内容,当返回值为-1时结束循环。

2.read方法(利用buffer读取文件)

这个稍稍有点难理解,我们一步一步分析:

【Java】基础41:什么叫IO流?

①创建输入流

其中文件里的内容为abcdefgh.

并创建一个buffer数组,长度为3,(buffer为缓存的意思)

②第一次读数据

将读到的数据放入buffer中,并返回读到的长度。

因为buffer的长度为3,所以每次读取读3个字节。

所以读到的是abc,长度为3。

③第二次读数据

读到的是def,长度为3。

buffer中def将abc覆盖掉了,所以打印def。

④第三次读数据

文件中只有最后两个字节了,

所以读到的是gh,长度为2

buffer中只覆盖了前两个字节,后面的第3个字节保持不变(gh将def覆盖得到ghf),所以打印ghf。

⑤第四次读数据

因为都读完了,根本就没有读文件,所以返回值为-1(注意不为0哦)

buffer没有改变,所以还是打印ghf。

以上就是利用buffer数组读取文件时的工作原理。

但这样太繁琐了,有没有简单的方法?

有的,使用while循环就好了。

3.read方法(利用buffer读取文件while循环)

【Java】基础41:什么叫IO流?
①使用while循环

当length不为-1时,一直循环执行read操作;

当length为-1时,表示文件读到了最后,所以结束循环。

②使用字符串偏移

最后一次的字符串长度我们只需要读取到的数据,也就是ghf只需要gh即可。

总结

【Java】基础41:什么叫IO流?