一、 概念及分类
- 概念
IO流用来处理设备之间的数据传输- Java对数据的操作是通过流的方式
- Java用于操作流的类都在IO包中
- 流按流向分为两种:输入流,输出流。
- 流按操作类型分为两种:
- 字节流 : 字节流可以操作任何数据,因为在计算机中任何数据都是以字节的形式存储的
- 字符流 : 字符流只能操作纯字符数据,比较方便。
以下篇章都是介绍IO流的字节流和字符流
- IO流常用父类
- 字节流的抽象父类:
InputStream
OutputStream - 字符流的抽象父类:
Reader
Writer
- IO程序书写
- 使用前,导入IO包中的类
- 使用时,进行IO异常处理
- 使用后,释放资源
以下一定要理解好,我们是相对于内存而言进行输入和输出,并不是站在使用者的角度,也就是说FileInputStream进行输入。是内存要从我们写的文档中,获取元素。输入到自己的缓冲区中,也就是需要进行读(read) 操作。而我们从java缓冲区中想要输出一些东西,也就是进行OutputStream,从缓冲区中将我们的想要的东西上写(Write)出来。
以下介绍字符流
二、 字符流FileReader
1.字符流是什么
- 字符流是可以直接读写字符的IO流
- 字符流读取字符, 就要先读取到字节数据, 然后转为字符. 如果要写出字符, 需要把字符转为字节再写出。
2.FileReader
案例:在本工程下,新建一个xxx.txt文档。往里面书写内容。
FileReader fileReader =new FileReader("xxx.txt");
int c;
while ((c=fileReader.read())!=-1) {
//通过项目默认的码表一次读取一个字符
System.out.print((char)c);
}
fileReader.close();
效果如下:
三、 字符流FileWriter
FileWriter fileWriter =new FileWriter("yyy.txt");
fileWriter.write("大家好,我是小学生"); //写字符串
fileWriter.write(97); //写一个字符
fileWriter.close();
效果如下:
四、 字符流的拷贝
FileReader fileReader =new FileReader("xxx.txt");
FileWriter fileWriter =new FileWriter("zzz.txt");
int c;
while ((c=fileReader.read())!=-1) {
fileWriter.write(c); //不用char强转
}
fileReader.close();
//Writer中有一个2k的小缓冲区,如果不关流,就会将内容写到缓冲区里面
fileWriter.close(); //关流,会将缓冲区的内容写入
效果如下:
tips:如果此时我们没有写关闭方法,我们会发现数据并没有写入。是因为Writer中有一个2k的小缓冲区,如果不关流,就会将内容写到缓冲区里面
五、 什么情况下使用字符流
- 字符流也可以拷贝文本文件, 但不推荐使用. 因为读取时会把字节转为字符, 写出时还要把字符转回字节。中间有一个转换的过程。而FileInputStream是直接字节接受,字节输出。
- 程序需要读取一段文本, 或者需要写出一段文本的时候可以使用字符流。(只读或者只写的情况下即可)
- 读取的时候是按照字符的大小读取的,不会出现半个中文
- 写出的时候可以直接将字符串写出,不用转换为字节数组
六、 字符流是否可以拷贝非纯文本的文件
- 不可以拷贝非纯文本的文件
- 因为在读的时候会将字节转换为字符,在转换过程中,可能找不到对应的字符,就会用?代替,写出的时候会将字符转换成字节写出去
- 如果是?,直接写出,这样写出之后的文件就乱了,看不了了
七、 自定义字符数组的拷贝
FileReader fileReader =new FileReader("xxx.txt");
FileWriter fileWriter=new FileWriter("yyy.txt");
char[] arr= new char[1024];
int len;
while ((len=fileReader.read(arr))!=-1) {
//将文件上的数据读取到字符数组中
fileWriter.write(arr,0,len);
//将字符数组中的数据写到文件上
}
fileReader.close();
fileWriter.close();
效果如下:
八、 带缓冲的字符流
- BufferedReader的read()方法读取字符时会一次读取若干字符到缓冲区, 然后逐个返回给程序, 降低读取文件的次数, 提高效率
- BufferedWriter的write()方法写出字符时会先写到缓冲区, 缓冲区写满时才会写到文件, 降低写文件的次数, 提高效率
BufferedReader bufferedReader =new BufferedReader(new FileReader("xxx.txt"));
BufferedWriter bufferedWriter =new BufferedWriter(new FileWriter("yyy.txt"));
int c;
while ((c=bufferedReader.read())!=-1) {
bufferedWriter.write(c);
}
bufferedReader.close();
bufferedWriter.close();
九、 readLine()和newLine()方法
- BufferedReader的readLine()方法可以读取一行字符(不包含换行符号)
读一行就是一行。 - BufferedWriter的newLine()可以输出一个跨平台的换行符号"\r\n"
BufferedWriter bufferedWriter =new BufferedWriter(new FileWriter("aaa.txt"));
String line;
while ((line=bufferedReader.readLine())!=null) {
bufferedWriter.write(line);
bufferedWriter.newLine();
//或者用下面方法
bufferedWriter.write("\r\n");
}
bufferedReader.close();
tips:注意: bufferedWriter.newLine();该方法可以跨平台使用。但是bufferedWriter.write("\r\n");只能在windows下系统有效。并且注意readLine()可以读取文本中每一行的字符,不包括换行符号。
十、 LineNumberReader
- LineNumberReader是BufferedReader的子类, 具有相同的功能, 并且可以统计行号
- 调用getLineNumber()方法可以获取当前行号
- 调用setLineNumber()方法可以设置当前行号
LineNumberReader lineNumberReader =new LineNumberReader(new FileReader("zzz.txt"));
String line;
//如果加上这一行代码
lineNumberReader.setLineNumber(100);
//会从第101行往后书写
while ((line=lineNumberReader.readLine())!=null) {
System.out.println(lineNumberReader.getLineNumber()+":"+line);
}
lineNumberReader.close();
此时我们访问该文档:
如果我们lineNumberReader.setLineNumber(100); 会从第100行开始阅读
十一、 使用指定的码表读写字符
- FileReader是使用默认码表读取文件, 如果需要使用指定码表读取, 那么可以使用InputStreamReader(字节流,编码表)
- FileWriter是使用默认码表写出文件, 如果需要使用指定码表写出, 那么可以使用OutputStreamWriter(字节流,编码表)
案例:
BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream("UTF-8.txt"), "UTF-8"));
//高效的用指定的编码表读
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream("GBK.txt"), "GBK"));
//高效的用指定的编码表写
int ch;
while((ch = br.read()) != -1) {
bw.write(ch);
}
br.close();
bw.close();