我们知道存在硬盘中数据是永久保存的,而在内存中的数据只是临时的。内存中的数据可以存入硬盘中,硬盘中的数据也也可以读入内存中。我们把这种数据的传输,可以看做一种数据的流动。通过IO流可以完成硬盘文件的读和写!
按照流动的方向,以内存为参考,分为:
输入流(input):流向内存是输入流,从别的地方(文件、键盘、网络、内存等)读取数据到当前程序中。
输出流(output):流出内存是输出流,从程序把数据写/输出到文件、屏幕(控制台)、网络、内存等中。
输入也叫做(Read)读取数据,输出也叫做(Write)写出数据。
第一种分类方式:按照数据流动方向进行分类,以内存作为参照物。输入流和输出流。
输入流:把数据从其他设备上读取到 内存中的流。
输出流:把数据从 内存 中写出到其他设备上的流。
第二种分类方式:按照数据处理单位分类。字节流和字符流。
字节流:以字节(Byte)为单位,读写数据的流。
字节流是按照字节的方式读取数据,一次读取 1byte,等同于一次读取8个二进制位。这种流是万能的,什么类型的文件都可以读取(文本、图片、声音、视屏)。
字符流:以字符(char)为单位,读写数据的流。
一次读取一个字符,这种流是为了方便读取普通文本文件而存在的。字符流只能用于读/写纯文本数据,纯文本主要有(txt,html,xml,properties,yml等)。如果都读写纯文本文件,字符流快于字节流。
第三种分类方式:按功能分类。节点流 和 包装流/处理流。
当构造方法中需要一个流的时候,被传进来的流叫做:节点流
外部负责包装的这个流,叫做:包装流[处理流]
对于包装流来说,只需要关闭最外层流就行,里面的节点流会自动关闭。(可以看原代码)
假设有一个file.txt文件(utf-8),里面的内容是:a中国bc。
其中字母在Windows系统中占1个字节,汉字在Windows中占2/3/4个字节
GBK、GB2312收编的汉字占2个字节
utf-8编码占用3个字节
超大字符集中的更大多数汉字要占4个字节
用字符流读取:
第1次读取:'a'
第2次读取:'中'
第3次读取:'国'
第4次读取:'b'
第5次读取:'c'用字节流读取:
第1次读取:'a'
第2次读取:'中'字符的一半
第3次读取:'中'字符的另外一半
第4次读取:'国'字符的一半
第5次读取:'国'字符的另外一半
第6次读取:'b'
第7次读取:'c'
java中所有的流都在:java.io 包下。
java IO流的四大家族:
java.io.InputStream 字节输入流
java.io.OutputStream 字节输出流
java.io.Reader 字符输入流
java.io.Writer 字符输出流
【注意】:类名以Stream结尾的是字节流,类名以Read/Write结尾的是字符流。四大家族的首领都是抽象类。(abstract class)。
所有流都实现了java.io.Closeable接口,都是可关闭的,都有close()方法。这是因为流是内存和硬盘之间的通道,耗费(占用)了很多资源,养成好的习惯,用完流,要及时关闭。
所有输出流实现了java.io.Flushable接口,都是可刷新的,都有flush()方法。养成好习惯,输出流在最终输出之后,一定要flush()刷新一下。这个flush()方法的作用就是清空管道(刷新的意思是将管道内剩余未输出的数据,强行输出完)。如果不刷新flush(),有可能丢失数据。
java.io包下需要掌握的流有16个 文件专属: java.io.FileInputStream java.io.FileOutputStream java.io.FileReader java.io.FileWriter 转换流(字节流-->字符流): java.io.InputStreamReader java.io.OutputStreamWriter 缓冲流专属: java.io.BufferedReader java.io.BufferedWriter java.io.BufferedInputStream java.io.BufferedOutputStream 数据流专属: java.io.DataInputStream java.io.DataOutputStream 标准输出流: java.io.PrintWriter java.io.PrintStream 对象专属流: java.io.ObjectInputStream java.io.ObjectOutputStream