字符流
字符流的由来:因为数据编码的不同,因而有了对字符进行高效操作的流对象,字符流本质其实就是基于字节流读取时,去查了指定的码表;而字节流直接读取数据会有乱码的问题(读中文会乱码),比如应对中文,每次就是读入一个字,而字节流在此情况下可能一次读取不了一个字,因为一个字不止一个字节
从另一角度来说:字符流 = 字节流 + 编码表
区别:
字符流,字符为单位
读写数据,字符流专门用于处理文本
文件。如果处理纯文本的数据优先考虑字符流,其他情况就只能用字节流了(图片、视频、等等)
字符输入流(Reader)
java.io.Reader
抽象类是字符输入流的所有类的父类,可以读取字符信息到内存中
FileReader类:
java.io.FileReader
类是读取字符文件类。- 构造时使用系统默认的字符编码和默认字节缓冲区。
FileReader的构造方法:
1、
FileReader(File file)
: 创建一个新的 FileReader ,给定要读取的File对象。
2、FileReader(String fileName)
: 创建一个新的 FileReader ,给定要读取的文件的字符串名称。(推荐)
构造举例,代码如下:
public class FileReaderConstructor throws IOException{
public static void main(String[] args) {
// 使用File对象创建流对象
File file = new File("D:\code\JavaDemo\a.txt");
FileReader fr = new FileReader(file);
// 使用文件名称创建流对象
FileReader fr = new FileReader("D:\code\JavaDemo\b.txt");
}
}
案例代码:
新建文本,名字为read,路径为D:\\code\\JavaDemo\\read.txt,内容为我是一个冷漠无情的机器人。
- 读取字符:
read
方法,每次可以读取一个字符的数据,提升为int类型,读取到文件末尾,返回-1
,循环读取,代码使用演示:
package com.logindemo.IO;
import java.io.FileReader;
import java.io.IOException;
public class readf1 {
public static void main(String[] args) {
FileReader fileReader = null;
int data = 0;
String path = "D:\\code\\JavaDemo\\read.txt";
try {
fileReader = new FileReader(path);
//一次读取单个字符
while ((data = fileReader.read()) != -1) {
System.out.print((char) data);
}
} catch (IOException e) {
throw new RuntimeException(e);
} finally {
try {
fileReader.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
}
2.利用数组,一次读取多个字符,这种方法更快
package com.logindemo.IO;
import java.io.FileReader;
import java.io.IOException;
public class readf2 {
public static void main(String[] args) {
FileReader fileReader = null;
char[] data = new char[8];
int len = 0;
String path = "D:\\code\\JavaDemo\\read.txt";
try {
fileReader = new FileReader(path);
//利用数组,一次读取多个字符,这种方法更快
while ((len = fileReader.read(data)) != -1) {
System.out.print(new String(data, 0, len));
}
} catch (IOException e) {
throw new RuntimeException(e);
} finally {
try {
fileReader.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
}
运行结果:读取正确~~~~
字符输出流(Writer)
java.io.Writer
抽象类是字符输出流的所有类的超类(父类),将指定的字符信息写出到目的地
FileWriter类:
java.io.FileWriter
类是写出字符到文件的类。- 构造时使用系统默认的字符编码和默认字节缓冲区
FileWriter构造方法:
1、
FileWriter(File file)
: 创建一个新的 FileWriter,给定要读取的File对象。
2、FileWriter(String fileName)
: 创建一个新的 FileWriter,给定要读取的文件的名称。(推荐)
public class FileWriterConstructor {
public static void main(String[] args) throws IOException {
// 第一种:使用File对象创建流对象
File file = new File("D:\code\JavaDemo\\a.txt");
FileWriter fw = new FileWriter(file);
// 第二种:使用文件名称创建流对象
FileWriter fw = new FileWriter("D:\code\JavaDemo\\b.txt");
}
}
案例代码:
package com.logindemo.IO;
import java.io.FileWriter;
import java.io.IOException;
// 文件输出流FileWriter案例:
public class writef1{
public static void main(String[] args) {
FileWriter fileWriter = null;
String path = "D:\\code\\JavaDemo\\write.txt";
char[] data = {'h', 'j'};
try {
//通过设置true变为追加模式
fileWriter = new FileWriter(path, true);
//fileWriter.write(1);
fileWriter.write('H'); //当前内容:H
fileWriter.write("吃饭了吗"); //当前内容:H吃饭了吗
fileWriter.write("Island早上好", 0, 2); //当前内容:H吃饭了吗Is
fileWriter.write(data, 0, 1); //当前内容:H吃饭了吗Ish
} catch (IOException e) {
throw new RuntimeException(e);
} finally {
//必须要将写入流关闭,才能将数据成功写入,否则就是空文件
try {
fileWriter.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
}
运行结果:写入成功~~~~
注意点 :
- 注意这个方法必须要在最后关闭输出流,数据才会成功写入文件
- 关闭资源时,与FileOutputStream不同。 因为内置缓冲区的原因,如果不关闭输出流,数据只是保存到缓冲区,无法保存到文件中。
- 但是关闭的流对象,是无法继续写出数据的。如果我们既想写出数据,又想继续使用流,就需要
flush
方法了。
flush
:刷新缓冲区,流对象可以继续使用。
close
:先刷新缓冲区,然后通知系统释放资源。流对象不可以再被使用了。
怎么理解呢?我们直接来一个小案例:
package com.logindemo.IO;
import java.io.FileReader;
import java.io.FileWriter;
public class FlushDemo {
public static void main(String[] args) throws Exception {
// 使用文件名称创建流对象
FileWriter fw = new FileWriter("D:\\code\\JavaDemo\\flush.txt");
// 写出数据,通过flush
fw.write('刷'); // 写出第1个字符
fw.flush();
fw.write('新'); // 继续写出第2个字符,写出成功
fw.flush();
// 写出数据,通过close
fw.write('关'); // 写出第1个字符
fw.close();
fw.write('闭'); // 继续写出第2个字符,【报错】java.io.IOException: Stream closed
fw.close();
}
}
运行结果:可以看到使用flush后流对象可以继续使用,成功写入刷新,但是使用close后流对象不可以再被使用了!!直接报错了!写入也失败了
总结一下:
flush()
这个函数是清空的意思,用于清空缓冲区的数据流;- 进行流的操作时,数据先被读到内存中,然后再用数据写到文件中,那么当你数据读完时,我们如果这时调用
close()
方法关闭读写流,这时就可能造成数据丢失,为什么呢?因为,读入数据完成时不代表写入数据完成,一部分数据可能会留在缓存区中,这个时候flush()
方法就格外重要了。