一、IO流的概念:
I:input输入
O:output输出
1 流的分类:
1.1 根据流向不同可以分:InputStream和OutputStream
1.2 根据数据源不同可以分为:FileInputStream、ZipFileInputStream等
1.3 根据内容的不同可以分为:字节流和字符流
2 Java程序中的流:
2.1 Java程序通过流从其他地方获取数据
2.2 数据源和目的地是相对的,如果以文件/数据库为中心,Java程序是数据源文件/数据数是目的地
2.3 如果以Java程序为中心,那么文件/数据库是数据源,Java程序为目的地
2.4 一般情况下,我们以程序为中心:
我们把数据源指向Java程序的流称为输入流(Input)
把Java程序指向数据源的流称作为输出流(Output)
3、Java针对输入输出提出两个顶级抽象类:
3.1 Java.io.InputStream:输入流
根据数据源的不同,InputStream有可以分为众多的子类
class FileInputStream extends InputStream(☆)
3.2 Java.io.OutputStream:输出流
根据数据源的不同,OutputStream也可以分为众多的子类:
class FileOutputStream extends OutputStream
二、划分:
1、按照流向来分:输入和输出流
2、按照处理的内容来分:字节流和字符流
3、按照功能来分:文件流、缓冲流、打印流、对象流、转换流、内存流、标准输入输出流...
三、字节流
调用:
1、FileInputStream():将磁盘上的文件中数据读取到Java程序中
构造方法: FileInputStream(String filePath)/FileInputStream(File file)
1.1 int read(byte[] bytes); 获取文件中的一个字节的数据
参数bytes:一次性尝试读取bytes.length个字节
如果数据源已经读完,那么这个方法返回为-1。
// 数据容量大小固定,当读取的数据字节数超过数组容量最值之后,从下一字节开始覆盖掉原来的对应下标的数据再存储下一数据
1.2 void close():关闭流,文件操作完后,关闭文件/释放资源。如果不释放资源,表示这个文件一直被Java程序占用,无法进行删除等操作。
1.3 int available():返回流中还有多个没有被读取的字节数,方法返回值为0代表读取完毕。
2、FileOutputStream():把Java程序中的数据输入到磁盘上的文件中
1.1 void write(int i); 将程序中的数据逐个的方式写入磁盘上的文件中
write(byte[] bytes):会将bytes数组中的所有内容写入磁盘上的文件中。
四、字符流
1、工作原理:使用通过字节将文件中的字节数据读取到内存当中
2、字符流的祖宗类:Reader 和 Writer
3、字符流:相对于字节流每次需要操作字节数数组而言,字符流可以直接操作字符。
4、 通过FileInputStream读取文件文件中的数据的时候,我们需要手动将读取到的byte数组转为字符串。
现在需要手动转的过程被封装到了FileReader中。
5、Reader类:
5.1 常用的子类:FileReader extends InputStreamReader extends Reader
① FileReader:
FileReader(File file)
FileReader(String filepath):绑定一个filepath指定的文件,从这个文件中获取
② 常用方法:
read():读取数据
close():关闭文件
flush():刷新缓冲区
当缓冲区不足8k的时候,必须手动刷新缓冲区,将缓冲区的数据写入到磁盘文件中,否则会导致数据丢失
缓冲区:进行转换的字节数据会存放在缓冲区,当缓冲区满了之后就会把字节数据通过FileOutputStream写入到磁盘上的文件中
6、Writer类:
6.1 FileWriter:
① FileWriter extends Writer
void write(char cbuf[]) throws IOException 相当于:void write(char cbuf[]) throws IOException
void write(char cbuf[], int off, int len) throws IOException
void write(int c) throws IOException
void write(Stirng str) throws IOException
void write(Stirng str,String off, len) throws IOException
② 常用方法:
write():把数据写入到磁盘
close():关闭文件
flush():刷新缓冲区
五、缓冲流
1、在Java程序不需要磁盘上的数据的时候,缓冲流的的底层就首先调用fis从磁盘上获取一部分方法缓冲区中,然后Java程序需要数据的时候
不是直接区磁盘上读取,而是缓冲区。
2、生活中的例子:你去看一个视频,但是你的网很卡,这个时候你就会暂停视频,让它缓冲一会儿,可以去干其他事情,等视频缓冲的差不多了然后再去看视频。
3、BufferedInputStream执行步骤:
3.1、当调用BIS的read方法,底层就会通过fis调用read(byte[] bytes)从文件中获取8kb的数据量,然后把8kb的数据放在缓冲区中,就拷贝1kb到bytes数组中。
3.2、下次调用BIS的read()方法的时候就不会去磁盘上读取数据,而从缓冲区中读取数据。
3.3、假设缓冲区中没有数据,它就进行第一步操作
// ①、真正去文件中读取字节数据的字节流
FileInputStream fis = new FileInputSt
// ②、创建缓冲流对象,并且规定缓冲区为4kb
BufferedInputStream bis = new BufferedInputStream
// ③、通过缓冲流读取数据(一次性读取一行)
byte[] bytes = new byte[1024];
int len;
while ((len = bis.read(bytes))!=-1){
System.out.println(new String(byt
}
// ④、释放资源,关闭流
bis.close();
六、转换流
1、转换流 = 字节流+编码表, 就是为了程序不要直接接触字节数据而且能看得懂的字符数据。
2、InputStreamReader: 字节输入流转为字符输入流
之前讲的FileReader就是InputStreamReader的一个子类: FileReader extends InputStreamReader
2.1 InputStreamReader的工作原理:
①、通过字节流(构造方法传入进来的字节)读取到字节数据
②、把上一步读取到的字节数据报错到缓冲区中
③、通过编码表将缓冲区中的字节数据转为具体的字符
3、OutputStreamWriter:字节输出流转为字符输出流
之前将的FileWriter就是OutputStreamWriter的一个子类
七、对象流
1、对象流概述:
用于从流中读取对象的,可以用于读写任意类型的对象
1.1 ObjectInputStream 称为 反序列化流,利用输入流从文件中读取对象
方法 readObject()
1.2 ObjectOutputStream 称为 序列化流,利用输出流向文件中写入对象
方法 writeObject()
1.3 特点:用于操作对象。可以将对象写入到文件中,也可以从文件中读取对象。
1.4 ObjectOutputStream在使用的时候,一定要保证保存的对象实现Serializable接口
1.5 注意:
使用对象输出流写出对象,只能使用对象输入流来读取对象
只能将支持 java.io.Serializable 接口的对象写入流中
2、对象流操作的4细节:
①、写入对象的顺序就是获取对象的顺序。
②、修改已经被写入文件的对象类的属性,再次从文件中读取该对象会报InvalidClassException异常
③、类的成员属性也要实现Serializable接口
④、静态变量属于类,不会被序列化到磁盘
3、使用对象输出流和读对象输入流写对象
Exception in thread "main" java.io.NotSerializableException:
Serializable:序列号,是一个标识接口,只起标识作用,没有方法
当一个类的对象需要IO流进行读写的时候,这个类必须实现该接口
4、解决对实现序列化接口出现的黄色警告问题
Exception in thread "main" java.io.InvalidClassException
当 Serialization 运行时检测到某个类具有以下问题之一时,抛出此异常
①、该类的序列版本号与从流中读取的类描述符的版本号不匹配
②、该类包含未知数据类型
③、该类没有可访问的无参数构造方法
5 transient:(瞬态) 标注的属性不会被序列化
八、打印流
1、PrintStream extends OutputStream
2、PrintWriter
println():打印并换行
print():打印不换行
3、打印重定向:
System.setIn(InputStream in)
System.setOut(OutputStream out)
九、标准输入输出流
1、标准输入流:
System.in, 数据源是控制台
2、标准输出流:
System.out,目的地是控制台
println:打印并且换行
println方法可以打印任何类型的数据:println(Object o)
底层是先调用对象的toString()转为字符串,然后把字符打印在控制台上
十、总结
按照流向来分:输入和输出流
按照处理的内容来分:字节流和字符流
按照功能来分:文件流、缓冲流、打印流、对象流、转换流、内存流、标准输入输出流...
不管使用那种流,只要是和文件操作相关最终就是使用(字节流操作)FileOutputStream或者FileInputStream写入或者读取到缓冲区,
然后再通过一系列的转换(字节-->字符-->,字节-->对象...)达到要求 (☆)