1. 字符流基础简介
1. 常见的编码格式
-
ASCII码:由一个字节表示,只支持一些基础字符和数字以及一些键盘上的符号…
-
UTF8: 万国码,支持所有国家的语言文字。针对Unicode码表的可变长字符编码,一般采用2个左右的字节表示一个字符。
-
GB2312: 是一种常见的简体中文编码,采用1个或2个字节表示一个字符。
-
GBK: 简体中文,对GB2312的扩充。
面对字符流不能像字节流一样处理,字节流是固定字节读取的。而字符在不同的编码方式中一个字符所占的字节大小是不同的,所以使用字符流的时候一定要注意编码格式问题防止出现乱码。
2. 字符流的父类(抽象类)
Reader字符输入流类,Writer字符输出流类。
2. FileReader 和 InputStreamReader
-
InputStreamReader类是一个Reader的实现类,其中InputStreamReader还派生出FileReader类。但是不建议使用FileReader类,InputStreamReader类派生出FileReader有利也有弊。
-
有利的一方面就是FileReader类可以简单化操作直接可以面向一个文件的URL地址进行操作,而InputStreamReader类必须基于一个InputStream的实现类。
-
弊端就是FileReader无法指定字符集的编码根据OS采用默认的编码格式。而InputStreamReader类在构造时是可以直接设置字符编码的。
//直接使用一个桌面文件地址构造 FileReader fr = new FileReader("C:\\Users\\Splay\\Desktop\\hello.txt"); //这里基于FileInputStream类构造实现 InputStreamReader isr = new InputStreamReader( new FileInputStream("C:\\Users\\Splay\\Desktop\\hello.txt"),"UTF8");//指定编码
-
除此之外FileReader类对于InputStreamReader类的扩充只扩充了自己的三种构造方法,其余所有的方法都来自InputStreamReader类。
-
InputStreamReader是字节流通向字符流的桥梁,它使用指定的字符编码读取字节并将其解码为字符。它使用的字符集可以由名称指定或显式给定,或者可以接受平台默认的字符集。每次调用 InputStreamReader 中的一个 read() 方法都会导致从底层输入流读取一个或多个字节。要启用从字节到字符的有效转换。
import java.io.*; public class Demo01 { public static void main(String[] args) { try { //hello.txt中放入 好好学习,天天向上。 InputStreamReader isr = new InputStreamReader( new FileInputStream("C:\\Users\\Splay\\Desktop\\hello.txt"),"UTF8"); System.out.println("当前编码格式: " + isr.getEncoding()); //获取字符编码 int value = isr.read(); //这里读取到返回的值是字符编码值,强转才是字符。 System.out.println((char)value); char [] c = new char[1024]; int len = 0; while((len = isr.read(c)) != -1){ //这里读到的len是成功读取到的字符长度。 System.out.println(new String(c,0,len)); } isr.close(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } }
3. FileWriter 和 OutputStreamWriter类
-
它们的关系和上面的关系差不多,同样推荐使用OutputStreamWriter类。
-
**FileWriter类可以控制是否对一个已存在的文件写入数据时:采用尾部追加的方式写入还是覆盖的方式写入;OutputStreamWriter类没有这个机制,它构造时会自动清理文件里的内容! **
//传入参数为true 采用append数据追加的形式写入数据 false或者默认是覆盖的形式写入数据。 FileWriter fw = new FileWriter("C:\\Users\\Splay\\Desktop\\hello.txt",true); OutputStreamWriter osw = new OutputStreamWriter( new FileOutputStream("C:\\Users\\Splay\\Desktop\\hello.txt"),"utf8");
-
append方法和write方法是一样的,底层是append调用write。不要被字面意思迷惑,它不是追加!
public Writer append(CharSequence csq) throws IOException { if (csq == null) write("null"); else write(csq.toString()); return this; }
-
对于输出流来说,需要注意一点Reader类没有的。就是一定要flush刷新流,保证回写的成功。
1. FileWriter追加测试
import java.io.*;
public class Demo01 {
public static void main(String[] args){
try{
FileWriter fw = new FileWriter("C:\\Users\\Splay\\Desktop\\hello.txt",true);
fw.write("我一定好好学习!"); //append和write方法一样,底层是append调用write。
fw.flush(); //刷新流
System.out.println("FileWriter流末尾追加成功!");
InputStreamReader isr = new InputStreamReader(
new FileInputStream("C:\\Users\\Splay\\Desktop\\hello.txt"),"UTF8");
char[] c = new char[1024];
int len = 0;
while((len=isr.read(c)) != -1){ //读取输出
System.out.println("成功读取: " + new String(c,0,len));
}
fw.close();
isr.close();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
2. OutputStreamWriter测试
import java.io.*;
public class Demo02 {
public static void main(String[] args) {
try{
//hello.txt中存放 好好学习,天天向上。我一定好好学习!
OutputStreamWriter osw = new OutputStreamWriter(
new FileOutputStream("C:\\Users\\Splay\\Desktop\\hello.txt"),"utf8");
System.out.println("OutputStreamWriter创建完毕,我们下面看看文件内容是否被清空?");
InputStreamReader isr = new InputStreamReader(
new FileInputStream("C:\\Users\\Splay\\Desktop\\hello.txt"),"UTF8");
char[] c = new char[1024];
int len = 0;
while((len=isr.read(c)) != -1){ //读取输出
System.out.println("1. 成功读取: " + new String(c,0,len)+"\n\n");
}
if(len == -1){
System.out.println("1. 读取失败!");
}
osw.write("hello world!");
osw.flush();
len = 0;
while((len=isr.read(c)) != -1){ //读取输出
System.out.println("2. 成功读取: " + new String(c,0,len)+"\n\n");
}
osw.close();
isr.close();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
4. 总结
-
FileReader 和 InputStreamReader推荐使用InputStreamReader,可以设置字符编码。
-
FileWriter 和 OutputStreamWriter同样推荐使用OutputStreamWriter,可以设置字符编码。
-
FileWriter可以设置对文件是采用追加还是覆盖的方式写入数据,OutputStreamWriter不能。
-
OutputStreamWriter创建时会直接对文件进行格式化,直接清空里面的数据。
-
FileWriter 和 OutputStreamWriter无论哪个类的append方法都是写入的意思,不是字面追加的意思!不是追加!不是追加!底层实现append方法是调用write方法。