字符流
当使用字节流读取文本文件的时候,可能会有一个小问题,就是遇到中文字符的时候,可能不会显示完整的字符,那是因为一个中文字符可能占用多个字节存储。所以java提供了一些字符流类,以字符为单位读写数据,专门用于处理文本文件。
- public void close():关闭此流并释放与此流相关联的任何系统资源
- public int read():从输入流读取一个字符
- public int read(char[] cbuf):从输入流中读取一些字符,并将它们存储到字符数组cbuf中。
FileReader类
java.io.FileReader类是读取文件的遍历类。构造时使用系统默认的字符编码和默认的字节缓冲区
小贴士:
- 字符编码:字符与字节对应规则,Windows系统中默认的中文编码是GBK编码表。IDEA中是UTF-8.
- 字节缓冲区:一个字节数组,用来临时存储字节数据
构造方法:
- FileReader(File file): 创建一个新的FileReader,给定要读取的File对象
- FileReader(String fileName): 创建一个新的FileReader,给定要读取的文件名称
当你创建一个流对象的时候,必须传入一个文件路径,类似于FileInputStream。
读取字符数据:
- 读取字符:read方法,每次可以读取一个字符的数据,提升为int类型,读取到文件的末尾,返回到-1,循环读取。
private static void show1() throws IOException {
//使用文件名创建流对象
FileReader fr = new FileReader("a.txt");
//定义变量,保存数据
int b;
//循环读取
while ((b = fr.read()) != -1) {
System.out.println((char) b);
}
fr.close();
}
- 使用字符数组读取:
read(char[] cbuf),每次读取b的长度个字符到数组中,返回读取到的有效字符个数,读取到末尾的时候,返回-1。
private static void show2() throws IOException {
//使用文件名称创建流对象
FileReader fr = new FileReader("a.txt");
//定义变量,保存有效的字符个数
int len;
//定义字符数组,作为装字符数据的容器
char[] cbuf = new char[2];
//循环读取
while ((len = fr.read()) != -1) {
System.out.println(new String(cbuf, 0, len));
}
//关闭资源
fr.close();
}
字符输出流(Writer)
java.io.Writer 抽象类是表示用于写出字符流的所有类的超类,将指定的字符信息写出到目的地。它定义了字节输出流的基本共性功能方法。
- void Write(int c):写入单个字符
- void write(char[] cbuf):写入字符数组
- abstract void write(char[] cbuf,int off,int len):写入字符数组的某一部分,off数组的开始索引,len写的字符个数
- void write(String str):写入字符串
- void write(String str,int off,int len):写出字符串的某一部分,off字符串的开始索引,len写的字符个数
- void flush() 刷新该流的缓冲
- void close():关闭此流,但要先刷新它。
FileWriter类:
java.io.FileWriter类写出字符到文件的便利类,构造时使用系统默认的字符编码和默认的字节缓冲区。
构造方法:
- FileWriter(File file):创建一个新的FileWriter,给定要读取的File对象
- FileWriter(String fileName):创建一个新的FileWriter,给定要读取的文件的名称
private static void show1() throws IOException {
//使用文件名创建流对象
FileWriter fw = new FileWriter("a.txt");
//写出数据
fw.write(97);
fw.write('b');
fw.write('c');
fw.write(30000);
//关闭资源的时候,与FileOutputStream不同,如果不关闭,数据只是保存在缓冲区,并未保存到文件
fw.close();
}
小贴士:
- 虽然参数为int 类型的四个字节,但是只会保留一个字符的信息输出。
- 未调用close方法,数据只是保存到了缓冲区,并未写到文件中。
关闭和刷新
因为内置缓冲区的原因,如果不关闭输出流,无法写出字符到文件中,但是关闭流对象,是无法继续写出数据的。如果我们既想写出数据,又想继续使用流,就需要flush方法了。
flush: 先刷新缓冲区,流对象可以继续使用。
close: 先刷新缓冲区,然后通知系统释放资源,流对象就不可以再次使用了。
private static void show2() throws IOException {
//使用文件名创建流对象
FileWriter fw = new FileWriter("a.txt");
//写出数据,通过flush
fw.write('刷');
fw.flush();
fw.write('新');
fw.flush();
//写出数据,通过close
fw.write('关');
fw.close();
/* fw.write('闭');//继续写出第二个字符,报错:java.io.IOException:Stream closed
fw.close();*/
}
小贴士:
即便是flush方法写出了数据,操作的最后还是要调用close方法,释放系统资源。
写出其他数据:
write(char[] cbuf) 和 write(char[] cbuf,int off,int len),每次可以写出字符数组中的数据
private static void show3() throws IOException {
//使用文件名创建流对象
FileWriter fw = new FileWriter("a.txt");
//字符串转换为字节数组
char[] chars = "黑马程序员".toCharArray();
//写出字符数组
fw.write(chars);
//写出从索引2开始,2个字节
fw.write(chars, 2, 2);
//关闭资源
fw.close();
}
写出字符串:
write(String str)和write(String str,int off,int len),每次可以写出字符串中的数据。
private static void show3() throws IOException {
//使用文件名创建流对象
FileWriter fw = new FileWriter("a.txt");
//字符串转换为字节数组
char[] chars = "黑马程序员".toCharArray();
//写出字符数组
fw.write(chars);
//写出从索引2开始,2个字节
fw.write(chars, 2, 2);
//关闭资源
fw.close();
}
续写和换行:
private static void show5() throws IOException {
//使用文件名创建流对象,可以续写数据
FileWriter fw = new FileWriter("a.txt", true);
fw.write("黑马");
fw.write("\r\n");
fw.write("程序员");
fw.close();
}
小贴士:
- 字符流,只能操作文本文件,不能操作图片,视频等非文本文件
- 当我们单纯读或者写文本文件的时候,使用字符流,其他情况使用字节流。