FileReader是使用默认码表读取文件, 如果需要使用指定码表读取, 那么可以使用InputStreamReader(字节流,编码表)
FileWriter是使用默认码表写出文件, 如果需要使用指定码表写出, 那么可以使用OutputStreamWriter(字节流,编码表)

使用默认的码表读写文本

有以下文件,字符格式为gbk,我们使用默认字符集读取该文本,再写到另一个utf-8.txt文件,看什么效果?

  1. 窗台上,小小的茉莉花开了。她的香,瞬间蔓延了整个屋内,让我禁不住心旷神怡。
@Test
public void demo1() throws IOException {
    //用默认编码表读写,出现乱码,默认以UTF-8读取
    FileReader fr = new FileReader("gbk.txt");//文件内容为gbk格式编码
    FileWriter fw = new FileWriter("utf-8.txt");//写入后乱码

    int c;
    while((c = fr.read()) != -1) {
        fw.write(c);
    }

    fr.close();
    fw.close();
}

当前JDK8, 默认字符集是在 Java 虚拟机运行时才确定的,取决于不同的操作系统、区域设置等因素。
当前windows 10,虚拟机默认字符集是UTF-8。

��̨�ϣ�СС�����򻨿��ˡ������㣬˲���������������ڣ����ҽ���ס�Ŀ�������

可以看到,写入的文本已经乱码。

使用指定字符集读写文本

这里我们用到了InputStreamReader 和 OutputStreamWriter。

InputStreamReader是从字节流到字符流的桥梁:它读取字节,并使用指定的charset将其解码为字符 。
它使用的字符集可以由名称指定,也可以被明确指定,或者可以接受平台的默认字符集。
每个调用InputStreamReader的read()方法之一可能会导致从底层字节输入流读取一个或多个字节。

OutputStreamWriter是从字符流到字节流的桥梁:向其写入的字符编码使用指定的字节charset 。
它使用的字符集可以由名称指定,也可以被明确指定,或者可以接受平台的默认字符集。

同样读取gbk.txt文件,这次我们指定字符集。

@Test
public void demo2() throws IOException {
    InputStreamReader isr = new InputStreamReader(new FileInputStream("gbk.txt"), "gbk");    //指定码表读字符
    OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("utf-8.txt"), "utf-8");    //指定码表写字符

    int c;
    while((c = isr.read()) != -1) {
        osw.write(c);
    }

    isr.close();
    osw.close();
    }
窗台上,小小的茉莉花开了。她的香,瞬间蔓延了整个屋内,让我禁不住心旷神怡。

这次,可以看到,可以正常显示文本了。

更高效的使用转换流

为了最大的效率,可以考虑在BufferedReader中包装一个InputStreamReader,或在BufferedWriter中包装一个OutputStreamWriter。

@Test
public void demo3() throws IOException {
    BufferedReader br =                                 //更高效的读
        new BufferedReader(new InputStreamReader(new FileInputStream("gbk.txt"), "gbk"));
    BufferedWriter bw =                                 //更高效的写
        new BufferedWriter(new OutputStreamWriter(new FileOutputStream("utf-8.txt"), "utf-8"));
    int c;
    while((c = br.read()) != -1) {
        bw.write(c);
    }

    br.close();
    bw.close();
}