一、IO流是什么
惯例引用百科的回答
流是一种抽象概念,它代表了数据的无结构化传递。按照流的方式进行输入输出,数据被当成无结构的字节序或字符序列。从流中取得数据的操作称为提取操作,而向流中添加数据的操作称为插入操作。用来进行输入输出操作的流就称为IO流。换句话说,IO流就是以流的方式进行输入输出 [1] .
我对IO流的理解就是”你的程序和系统之间读写文件的操作就是IO操作,和系统之间读写用的东西就是IO流”。
JAVA IO流就是JAVA程序和操作系统之间通信用的方法。
二、JAVA IO系统脑图
给大家看下JAVA IO的脑图
自己画的JAVA的脑图,如果有需要原文件的去我公众号,发送:JAVA IO,就可以得到脑图的原文件了,带黄色文件夹标注的是我自己写的注释嗷。
什么你还不知道我公众号,微信搜索,千珏(jue),就可以关注到我了。
三、JAVA IO流详解
在这里由于篇幅的原因我只讲解JAVA IO流中的字节流和字符流,别的就等以后再写,比如:NIO AIO BIO这些,以后有时间抽出时间出来写一篇,要是想看的记得点个关注哦。
下面进入正题:
3.1 字节流和字符流的区别
字节流和字符流操作的本质区别只有一个:字节流是原生的操作,字符流是经过处理后的操作。
画个图,字节流在操作时不会用到缓冲区,也就是不会用到内存,文件本身直接操作的,而字符流在操作时使用了缓冲区,通过缓冲区再操作文件,看下图:
为什么要有字符流而不直接用字节流呢?
我相信有些读者心里肯定要问这个问题,我刚开始学习的时候也想过这个问题,为什么不直接用字节流解决呢,还非要搞个字符流出来呢。
我的理解就是字节流处理多个字节表示的东西的时候有可能会出现乱码的问题,比如汉字,用字节流读取的时候有可能因为一位字节没有读到就变成了乱码,字符流呢就完美解决了这个问题,字符流你们可以这样理解,字节流和编码表的组合就是字符流。因为有了编码表所以可以确定这个汉字有多少个字节,这样字节流就可以根据位数准确的读写汉字了。
以上纯为个人理解,如有不对的地方请在评论区给我留言哦。
3.2 字节流
字节流顾名思义就是通过字节直接操作字符,更底层一些。
字节流最基础的两个类就是 InputStream
和 OutputStream
,根据这两个派生而来类都含有 read()
和 write()
的基本方法,用于读写单个字节或者字节数组。
3.2.1 InputStream 和 OutputStream类
InputStream类是一个抽象类 ,是所有字节输入流类的父类。
OutputStream类是一个抽象类,是所有字节输出流的父类
InputStream的常见子类有:
- FileInputStream:看这个名字就知道用于从文件中读取信息。
- ByteArrayInputStream: 字节数组输入流,
- ObjectInputStream:序列化时使用 一般和ObjectOutputStream一起使用
- FilterInputStream: 过滤输入流,为基础的输入流提供一些额外的操作。
OutputStream的常见子类有:
- FileOutPutStream: 文件输出流对文件进行操作
- ByteArrayOutputStream: 字节数组输出流
- ObjectOutputStream: 序列化时使用 一般和OjbectInputStream一起使用
- FilterOutputStream:过滤输出流,为基础的输出流提供一些额外的操作。
我们一个一个过要不然怎么能叫一文带你看懂JAVA IO流了呢,那样不就是标题党了吗[滑稽]。
3.2.1.1 FileInputStream 和 FileOutPutStream类
1) FileInputStream 和 FileOutPutStream概念
FileInputStream是文件字节输入流,就是对文件数据以字节的方式来处理,如音乐、视频、图片等。
FileOutPutStream是文件字节输出流,
2)FileInputStream里面的方法
1 | 复制代码//通过文件的名字来创建一个对象 |
由于篇幅起见FileOutputStream代码里面的方法我就不仔细的带你们看了(我不会说我是因为懒才不带你们看的,溜。
一般常用的方法就几个,举个例子,往D盘下面hello.txt里面输入“hello world”
1 | 复制代码public class Test { |
常用的就上述代码里面的三种方法。
3.2.1.2 ByteArrayInputStream和ByteArrayOutputStream
1)ByteArrayInputStream和ByteArrayOutputStream概念
ByteArrayInputStream是字节数组输入流,它里面包含一个内部的缓冲区(就是一个字节数组 ),该缓冲区含有从流中读取的字节。
ByteArrayOutputStream是字节数组输出流
2)ByteArrayInputStream里面的方法
1 | 复制代码//通过byte数组来创建对象 |
由于篇幅起见ByteArrayOutputStream代码里面的方法我就不仔细的带你们看了(我不会说我是因为懒才不带你们看的,溜
举个例子,从一个字符串读取数组
1 | 复制代码public class Test { |
如上代码所示,我平时常用的也就这几个方法。
3.2.1.3 ObjectInputStream 和ObjectOutpuStream
1)概念
ObjectInputStream是反序列化流,一般和ObjectOutputStream配合使用。
用ObjectOutputStream将java对象序列化然后存入文件中,然后用ObjectInputStream读取出来
这个类的作用,我的理解是有些类在这个程序生命周期结束后,还会被用到所以要序列化保存起来
2)ObjectInputStream 和 ObjectOutpuStream 基本方法
常用的其实就两个方法
1 | 复制代码public final Object readObject(){} |
1 | 复制代码 class Data implements Serializable { |
3.2.1.4 FilterInputStream 和 FilterOutputStream
1) 概念
FilterInputStream和FilteOutputStream分别是过滤输入流和过滤输出流,他们的作用是为基础流提供一些额外的功能
2)FilterInputStream 和 FilterOutputStream的常用子类
FilterInputStream常用子类
- DataInputStream:可以从流中读取基本数据类型,与DataOutpuStream配合一起使用
- BufferedInputStream:可以从缓冲区中读取数据,不用每次和文件的操作都进行实际操作了。
FilterOutputStream常用子类
- DataOutputStream:可以向文件中写入基本类型的数据
- PrintStream:用于产生格式化的输出
- BufferedOutputStream:通过缓冲区像文件中写入数据。
DataInputStream基本类型写入方法。
1 | 复制代码// 将一个 byte 值写入流中。 |
测试一下方法试试
1 | 复制代码public class Test { |
BufferedInputStream和BufferedOutputStream我另开一篇文章写,里面要介绍的东西很多,一篇文章介绍不完。
emmm,还有字符流下篇文章写,今天是完不成了,觉得这篇文章还可以想看下一篇文章的关注我呀,或者可以关注我公众号:千珏呀,后台留言给我呀,是千珏(jue),不是千钰。
3.3 字符流
3.3.1 Reader类和wirter类
字符流:就是在字节流的基础上,加上编码,形成的数据流
字符流出现的意义:因为字节流在操作字符时,可能会有中文导致的乱码,所以由字节流引申出了字符流。
字符流最基础的两个类就是 Reader
和 wirter,根据这两个派生而来类都含有
read()和
write()` 的基本方法。
处理图片、视频、音乐的时候还是用字节流吧,处理文本文件的时候用字符流会好很多。
Reader类常见子类有:
- FileReader:文件输入流
- BufferedReader: 带缓冲区的字符输入流
Writer类常见子类有:
- FileWriter:文件输出流
- BufferedWriter:带缓冲区的字符输出流
3.3.1.1 FileReader类和FileWriter类
直接看实例吧
1 | 复制代码public class Test { |
FilerWriter 和FileReader 没啥好讲的,具体常用的方法也就上面的,具体使用我也写在注释上面了。
3.3.1.2 BufferedReader类和BufferedWriter类
1 | 复制代码public class Test { |
写下面的程序的时候还有一点小插曲,我调用close方法关程序的时候,我调用了两次bufferedReader.close();这就会导致我的文件里面没有数据,痛哭,加了flush发现之后发现文件里面又有数据了,这个时候突然间有个疑问,难道是BufferedWriter的close()方法里面没有调用flush()吗,要自己手动的调用 flush(),淦,那也太蠢了吧,于是去源码里面看了一眼。
1 | 复制代码public void close() throws IOException { |
源码里面是有flush()操作的呀,为什么我的程序出问题,一顿检查之后 发现文末写了两个bufferedReader的关闭方法,好吧为自己的愚蠢浪费了十分钟的时间QAQ。
四、总结
一般大佬都有总结 ,我也写个总结吧,也算是跟个风。
总的来说这篇文章写的很差,本来想带你们详细看下字节流和字符流的,结果因为年末的时候事情太多,导致我没有办法完成这一事情,只能简略的带你们看看io是怎么用的,并没有看io流为什么能这样用,没有看io流的实现,本质是想一个源码一个一个源码的过一边,一是因为时间不够,二是因为篇幅太长太枯燥,怕你们也看不下去,只能等以后出单章一个类一个类的源码解析看看,如果你们想看的话,给我留言吧。
这次不是太满意 ,希望下篇文章可以写的满意些吧。
各位看官觉得写得还可以的,点个关注吧。
本文转载自: 掘金