java对于文件的基本操作流程
重难点解析
1.熟悉java流的两种分类方法
按流向区分
输出流--------OutputStream和Writer作为基类
输入流--------InputStream和Reader作为基类
按照处理数据单元划分
字节流---------字节流输入InputStream基类/字节流输出流OutputStream基类
字符流---------字符流输入Reader基类/字符流输出Write基类
重点:
字节流Stream按照字节的方式读取数据,一次读取1个字节byte,等同于一次读取8个二进制位。这种流是万能的,什么类型的文件都可以读取。包括:文本文件,图片,声音文件,视频文件等;
字符流Reader/Write按照字符的方式读取数据,一次读取一个字符,这种流是为了方便读取普通文本文件而存在的,字符流不能读取:图片、声音、视频等文件。只能读取纯文本文件,连word文件都无法读取。
所以后续的二进制文件(图片,视频,文档)和object对象读取输出都是在字节流基础上进行包装操作.
IO流的分类
文件专属:
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.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
(注:在学习过程中会发现OutputStream中会用到write()方法,InputStream中会用到read()方法,这两种方法都是所对应的Stream(字节流基类)的实例方法而不是继承于Writer和Reader类,而Reader和Writer类中也含有相应的read()和write()方法,不要混淆方法和类的关系)
(注:Writer和Reader都是抽象类
OutputStreamWriter是Writer的子类(注意不是OutputStream的子类),而FileWriter是OutputStreamWriter的子类,所以FileWriter是Writer的孙子类.
InputStreamReader是Reader的子类(注意不是InputStream的子类),而FileReader是
InputStreamReader的子类,所以FileReader是Reader的孙子类.
)
【文件的写入与写出】
FileInputStream / FileOutputStream
输入流对象的两种读取方式,一种是直接用read()方法依次读取数据流中下一个字节,还有一种是将读取的数据存储在缓存区数组中,并返回实际读取的字节数(int类型),为什么read方法返回值是int类型而不是byte类型,解释如下.
此外对fis输入流对象while里的readCount = fis.read(bytes) != -1进行一下说明,依旧是扒源码。可以看出,调用这个read(bytes)方法返回的是从流中读取的字节数,当没有可用的输入时,返回-1。
fos输出流fos.write(bytes, 0, readCount)中,bytes为传输的数据,0为单次传输的起始下标,len表示单次传输的长度。
FileReader / FileWriter
FileReader文件字符输入流,FileWriter文件字符输出流。和FileOutputStream/FileInputStream类似,但只能输出普通文本。
BufferedReader / BufferedWriter
BufferedReader带有缓冲区的输入流,使用这个流的时候不需要自定义char数组,自带缓冲。
通过构造函数我们可以看出,调用BufferedReader时需要传入一个Reader类型的文件参数。当一个流的构造方法中需要一个流的时候,这个被传进来的流被叫做:节点流。外部负责包装这个流,叫做包装流/处理流。
通过源代码可以看出,BufferedReader在调用close()方法的时候,已经对节点流进行了关闭。所以对于包装流来说,只需要关闭最外层流就行,里面的节点流会自动关闭。
public static void main(String[] args) throws Exception{
// FileReader就是节点流。
FileReader reader = new FileReader("文件路径");
// BufferedReader就是一个包装流/处理流。
BufferedReader br = new BufferedReader(reader);
String s = null;
while((s = br.readLine()) != null){
System.out.println(s);
}
// 关闭流
br.close();
}
上面方法中只能传一个字符流,不能传字节流,当我们输入的为字节流的时候,需要先转换为字符流。所以需要通过转换流转换(InputStreamReader将字节流转换成字符流)
当然,上面代码也可以合并成下面一行代码:
BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream("文件路径")));
BufferedWriter
BufferedWriter和上面的定义类似,代码如下:
public static void main(String[] args) throws Exception{
BufferedWriter br = new BufferedWriter(new FileWriter("文件路径"));
// 或new一个FileOutputStream字节转换流
BufferedWriter br2 = new BufferedWriter(new OutputStreamWriter(new FileOutputStream("文件路径", true)));
// 开始写
br.write("hello world");
br.flush(); // 刷新
br.close(); // 关闭最外层
}