上一篇文章中,我们在提到 IO 流的概念时说到 IO 流分为两大类,一个是字节流,我们已经在上一篇文章中做了复习,而本篇文章的 IO流复习就从另一大类字符流来开始。
什么是字符流
上一篇文章中我们说过字符流一般只能操作的是存文本数据,而字节流可以操作很多类型数据(文本,图片,音频,视频等)
字符流是可以直接读写字符的IO流
计算机中存储的是字节数据,字符流读取字符,就要先读取到字节数据, 然后转为字符。当要写出字符,则需要把字符转为字节再写出
FileReader 和FileWriter
上一篇文章中已经提到过字符流的父类是Reader 和Writer,但是他们都是接口,不能直接new出对象,当我们要操作文本中的字符,字符流中给我提供了两个类FileReader 和FileWriter,他们的操作和字节流的FileInputStream 和 FileOuputStream基本是一样的。
字符的输入与输出
/**
*
* @author 毛麒添
* FileReader 读取字符 操作的是项目根目录中给的文件
*/
public class Demo_FileReader {
public static void main(String[] args) {
FileReader fr=null;
try {
fr=new FileReader("aaa.txt");
int a;
while((a=fr.read())!=-1){
//FileReader。read()得到的是对应的码表值,将其强转就可以得到相应的字符
//汉字字符对应两个字节一般以负数形势表现,底层读取判定是负数则一次读取两个字节,也就解释了为什么可以读取一个字符
System.out.print((char)a);
}
fr.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
*
* @author 毛麒添
* 输出字符 操作的是项目根目录中给的文件
*/
public class Demo_FileWriter {
public static void main(String[] args) {
try {
FileWriter fw=new FileWriter("bbb.txt");//如果要在末尾添加则,选择构造方法中有两个参数的,填入true
fw.write("我像风一样自由!!!!!!");
fw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
运行结果:
aaa.txt文件内容.png
FileReader读取一个字符程序运行截图.png
FileWrite输出字符运行结果.png
字符流的拷贝
/**
* @author 毛麒添
* 字符流的拷贝
*/
public class CharIo_copy {
public static void main(String[] args) {
FileReader fr=null;
FileWriter fw=null;
try {
fr=new FileReader("aaa.txt");
fw=new FileWriter("ccc.txt");//不存在则会自动创建
int a;
while((a=fr.read())!= -1){
fw.write(a);
}
//一定不能忘记关闭流,不关流,则输出文件中不会有内容,父类Writer中定义了缓存区,如果流不关闭,则输出内容还在缓冲区,不会出现输出字符
fr.close();
fw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
运行结果:
字符流拷贝输出结果.png
注意
什么情况下使用字符流
字符流也可以拷贝文本文件, 但不推荐使用其来拷贝文件. 因为字符流读取时会把字节转为字符, 写出时还要把字符转回字节,太过于耗费资。但是当程序需要读取一段文本, 或者需要写出一段文本的时候可以使用字符流(只读或者只写),读取的时候是按照字符的大小读取的,不会出现半个中文,写出的时候可以直接将字符串写出,不用转换为字节数组
字符流是否可以拷贝非纯文本的文件
答案当然是不可以拷贝非纯文本的文件。因为在读的时候会将字节转换为字符,在转换过程中,可能找不到对应的字符,就会用 “ ? ” 代替,写出的时候会将字符转换成字节写出去 如果是“?”,直接写出,这样写出之后的文件就乱了,也就是损坏了文件
与FileInputStream 和 FileOuputStream一样,字符流也可以定义字符数组进行拷贝和使用带缓冲的字符流来进行拷贝(BufferedReader和BufferedWriter )
/**
*
* @author 毛麒添
* 字符数组的拷贝
*/
public class Char_Arry_Copy {
public static void main(String[] args) throws IOException {
FileReader fr=new FileReader("aaa.txt");
FileWriter fw=new FileWriter("ccc.txt");
char[] arr=new char[1024];
int len;
while((len= fr.read(arr))!= -1){//将文件中的数据读取到字符数组中
fw.write(arr, 0, len); //将字符数组中的数据写入到文件中
}
fr.close();
fw.close();
}
}
/**
*
* @author 毛麒添
* 带缓冲区的字符流
*/
public class Char_Buffer {
public static void main(String[] args) throws IOException {
BufferedReader bf=new BufferedReader(new FileReader("aaa.txt"));
BufferedWriter bw=new BufferedWriter(new FileWriter("ccc.txt"));
int a;
while((a= bf.read())!= -1){
bw.write(a);
}
bf.close();
bw.close();
}
}
readLine()和newLine()方法
readLine()是BufferedReader的方法,它的作用读取一行字符(不包含换行符号)
newLine()是BufferedWriter的方法,它的作用为输出一个跨平台的换行符号"\r\n"(该方法在mac Window linux三个平台通用)
下面来个小例子来对readLine()和newLine()两个方法应用
/**
*
* @author 毛麒添
* 将一个文本文档上的文本反转,第一行和倒数第一行交换,第二行和倒数第二行交换
*/
public class Reversal_text {
public static void main(String[] args) throws IOException {
//获取文本文档的字符输入输出流
BufferedReader bf=new BufferedReader(new FileReader("aaa.txt"));
BufferedWri