一、大纲
1、流的分类
- 根据操作数据单位:字节流、字符流
- 根据数据流向:输入流、输出流
- 根据流的角色:节点流和处理流
2. 流的体系结构(只说重要的流)
抽象基类 | 节点流(文件流) | 缓冲流(处理流的一种) |
InputStream | FileInputStream | BufferedInputStream |
OutputStream | FileOutputStream | BufferedoutputStream |
Reader | FileReader | BufferedReader |
Writer | FileWriter | BufferedWriter |
怎么从流的类名判断出是什么类型的流?
- Input和Reader代表输入流 ,Output和Writer代表输出流
- 有File代表节点流,无File代表处理流
- 有Stream代表字节流,无Stream代表字符流
二、 FileReader类
——作用就是将文件里的文本内容读取到控制台中
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
public class HTIO {
public static void main(String[] args) throws IOException{
//实例化对应的File类,指明要操作的文件
File file1 = new File("C:\\Users\\Administrator\\Desktop\\hello1.txt");
//提供具体的流
FileReader fr = new FileReader(file1);
//数据的读入
int data;
while ((data = fr.read()) != -1){
System.out.print((char) data);
}
//hello
//4.关闭流(注意一定要关闭,否则有可能造成内存泄漏)
fr.close();
}
}
- 鼠标放在read()上两秒后会出现此方法的说明:返回的是一个int,即字符对应的ASCI码,而且是每执行一次fr.read(),指针偏移一次进而返回一个字符的ASCI码,在sout的时候强转为(char)。当read()返回-1时代表文件已经读完。
- 如果不在 public static void main(String[] args) 上 throws IOException,new FileReader(file1)、fr.read()、fr.close()都会让你抛出异常,让程序看着比较混乱
- 会抛出异常的原因是有可能文件不存在
- 但是这种做法的缺点是:在fr.read()处阻塞,抛出异常,直接停止程序,导致close()无法执行,则创建流之后不能关闭流
- 下面是用try-catch-finally改进优化
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
public class HTIO {
public static void main(String[] args){
FileReader fr = null;
try {
//1.实例化对应的File类,指明要操作的文件
File file1 = new File("C:\\Users\\Administrator\\Desktop\\hello1.txt");
//2.提供具体的流
fr = new FileReader(file1);
//3.数据的读入
int data;
while ((data = fr.read()) != -1){
System.out.print((char) data);
}
//hello
} catch (IOException e) {
e.printStackTrace();
} finally {
//4.关闭流(注意一定要关闭,否则有可能造成内存泄漏)
try {
fr.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
- 选中要try的代码块,ctrl alt t,选中try catch finally
- 把close语句方法finally中,即不管前面的操作出现什么异常,finally的语句一定会执行
- 举一个经典的例子来说明try-catch-finally:一个人去上厕所,中间可能遇到拉稀、掉厕所等等异常,然后用catch中去解决,但是最后都要擦屁股,也就是finally
try{一个人去上厕所}
catch{解决措施}
finally{擦屁股}
读文件总流程:
1.实例化File类 2.实例化流的类 3.读入操作 4.关闭流
三、read(char[] cbuf)方法详解
- 从中可以看到read()方法中可以传入的参数
- 常用的FileReader.read()的两个重载方法:1.空参 2.参数:char[] cbuf
- read(char[] cbuf)原理:每次执行此方法会读取五个字符到char[] cbuf中,下次执行时会读取接下来的五个字符。返回值是本次读取的字符个数,读取到最后会返回-1。
- 需要注意:下面这个程序,倒数第二次数组中读取到的是 [ython], 最后一次读取的时候因为只剩一个'c',覆盖cbuf的第一个位置,变成 [cthon]
桌面上hello1.txt文件中的内容:helloworldjavapythonc,任务:读取文件内容
错误写法:
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
public class HTIO {
public static void main(String[] args){
FileReader fileReader = null;
try {
File file = new File("C:\\Users\\Administrator\\Desktop\\hello1.txt");
fileReader = new FileReader(file);
char[] cbuf = new char[5];
int num;
while ((num=fileReader.read(cbuf))!=-1) {
for(int i=0;i<cbuf.length;i++){
System.out.print(cbuf[i]);
}
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
fileReader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
//helloworldjavapythoncthon
}
}
- 错误原因:倒数第二次数组中读取到的是 [ython], 最后一次读取的时候因为只剩一个'c',覆盖cbuf的第一个位置,变成 [cthon]
正确写法:
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
public class HTIO {
public static void main(String[] args){
FileReader fileReader = null;
try {
File file = new File("C:\\Users\\Administrator\\Desktop\\hello1.txt");
fileReader = new FileReader(file);
char[] cbuf = new char[5];
int num;
while ((num=fileReader.read(cbuf))!=-1) {
for(int i=0;i<num;i++){
System.out.print(cbuf[i]);
}
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
fileReader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
//helloworldjavapythonc
}
}