这节课来讲讲转换流
在讲转换流之前了,我们先讲讲字符的编码与解码。
首先,我们知道计算机里所有数据都是以二进制的形式存储的,.java文件想要运行必须先被编译成.class字节码文件,这里我们提到了一个词,字节码,或者说字节,以往一直没机会,这次就来带大家看看字节码文件。

这些以.class为后缀名的文件就是.class文件,这些文件的内容全是字节。我们打开来看看

看不懂,对不对?我也看不懂,因为这是给计算机看的。
人看的懂的是字符,计算机能看懂的是字节,那么如何将计算机看得懂的字节变成人看得懂的字符呢?又如何将人看得懂的字符变成计算机看得懂的字节呢?
编码:
将字符转换成字节的过程叫编码,编码指按照一定的规则将字符转换成字节
解码:
将字节转换车字符的过程叫解码,解码值按照一定的规则将字节转换成字符
下面来看一段java代码

看介绍里可以看出String 的构造器可以对字节进行解码,而且可以按照指定的字符集进行解码
说一下字符集: 就是一种编码或者解码的规则,常见的字符集有: GBK,gb2312,UTF-8(这个我们以后用的最多)

String 可以解码,自然也提供了编码的方法,就是使用getBytes方法。
Demo 01:
public static void main(String[] args) throws UnsupportedEncodingException {
    //先来new一个byte数组
    byte[] bytes = "我爱java".getBytes("UTF-8");
    String str = new String(bytes, "UTF-8");
    System.out.println(str);
}输出:
Java
注意: 如果编码字符集和解码字符集不相同的话,会出现乱码
Demo 02:
public static void main(String[] args) throws UnsupportedEncodingException {
    //先来new一个byte数组
    byte[] bytes = "我爱java".getBytes("UTF-8");
    String str = new String(bytes, "GBK");
    System.out.println(str);
}输出:
鎴戠埍java
顺便一提:如果字符集不同的话,只有不在0-127之间的字符才会出现乱码
接下来看看乱码的第二个原因: 字节不完整
首先有一个问题,把一个字符转换成一个字节数组,那么这个字节数组的长度是多少?
Demo 03:
public static void main(String[] args) throws UnsupportedEncodingException {
    byte[] bytes = "1".getBytes();
    System.out.println(bytes.length);   //1
    bytes = "a".getBytes();
    System.out.println(bytes.length);   //1
    bytes = "我".getBytes();System.out.println("我".length());   //1
    System.out.println(bytes.length);   //3
}结论: 0-127之间的字符转字节一个字符对应一个字节,中文的一个汉字对应3个字节,而且,一个汉字只是一个字符
Demo 04:
public static void main(String[] args) throws UnsupportedEncodingException {
    byte[] bytes = "我".getBytes();
    String str = new String(bytes,0,1);
    System.out.println(str);    //乱码
    str = new String(bytes,0,3);
    System.out.println(str);    //正常
}结论: 乱码的第二个原因: 字节不完整
OK,讲清楚编码和解码之后,我们再来讲讲转换流 。
转换流: 将字节流转换成字符流的流,主要作用是处理字符编码
转换流常用的两个类: InputStreamReader, OutputStreamWriter
InputStreamReader:
InputStreamReader 是字节流通向字符流的桥梁:它使用指定的 charset 读取字节并将其解码为字符。它使用的字符集可以由名称指定或显式给定,或者可以接受平台默认的字符集。
构造器:

主要用最后一个 InputSteamReader(InputStream in, String charsetName)
下面来看一个小例子:
Demo 05:
public static void main(String[] args) throws FileNotFoundException, UnsupportedEncodingException {
        //这里我么有异常直接抛出,就不捕获了,方便看
//        BufferedReader reader = new BufferedReader(new FileReader(new File("F:\\code\\java\\2.txt")));
        //这里我们就发现了一个问题,我们在用字符流读取文件的时候,没办法指定字符集编码,这是有很大问题的
        //因为编译器的默认编码可能和文件的编码不一样,这样就会造成乱码的现象
        //所以我们希望能指定编码,同时又去用字符流去读取(加缓冲流是提高效率),这个时候就需要转换流
        //转换流有两个: InputStreamReader, OutputStreamWriter
        //这样我们就可以使用指定字符集编码的字符缓冲流来读取文件了,看起来有点麻烦,实际上了解了原理以后非常的好写,我们来重新写一遍
        /**
         * 第一步 new一个BufferedReader,构造器需要一个Reader类型的参数
         * 第二步 由于转换流InputStreamReader是Reader的子类,所以可以把InnputStreamReader对象 传进去
         * 第三步 InputStreamReader需要一个InputStream 和 一个 字符串(表示字符集编码)
         */
        BufferedReader reader = new BufferedReader(
                new InputStreamReader(new FileInputStream(new File("F:\\code\\java\\2.txt")), "UTF-8")
        );   
        //这样,一个可以指定字符编码集的字符 缓冲流就构造好了,剩下的就和以前讲的一样即可
        //OutputStreamWriter和InputStreamReader差不多,只不过一个读,一个写
        BufferedWriter writer = new BufferedWriter(
                new OutputStreamWriter(new FileOutputStream(new File("F:\\code\\java\\3.txt")),"UTF-8")
        );
    }









