08 转换流


1 问题引出:不同编码读取乱码问题

1. 之前我们使用字符流读取中文是否有乱码?

● 没有的,因为代码编码和文件编码都是UTF-8。

2. 如果代码编码和文件编码不一致,使用字符流直接读取还能不乱码吗?

会乱码

● 文件编码和读取的编码必须一致才不会乱码。

步骤:使用相同编码读取不同编码的文件内容

需求:分别使用如下两种方式读取文件内容

①代码编码是UTF-8,文件编码也是UTF-8,使用字符流读取观察输出的中文字符结果。

②代码编码是UTF-8,文件编码使用GBK,使用字符流读取观察输出的中文字符结果

【案例】

public class InputStreamReaderDemo01 {
    public static void main(String[] args) throws Exception {
        // 代码UTF-8   文件 GBK  "D:\\resources\\data.txt"
        // 1、提取GBK文件的原始字节流。   abc 我
        //                            ooo oo
        InputStream is = new FileInputStream("D:\\resources\\data.txt");
        // 2、把原始字节流转换成字符输入流
        // Reader isr = new InputStreamReader(is); // 默认以UTF-8的方式转换成字符流。 还是会乱码的  跟直接使用FileReader是一样的
        Reader isr = new InputStreamReader(is , "GBK"); // 以指定的GBK编码转换成字符输入流  完美的解决了乱码问题

        BufferedReader br = new BufferedReader(isr);
        String line;
        while ((line = br.readLine()) != null){
            System.out.println(line);
        }
    }
}

2 字符输入转换流

1. 如果代码编码和文件编码不一致,使用字符流直接读取还能不乱码吗?

会乱码。

2. 如果如何解决呢?

● 使用字符输入转换流

● 可以提取文件(GBK)的原始字节流,原始字节不会存在问题。

● 然后把字节流以指定编码转换成字符输入流,这样字符输入流中的字符就不乱

字符输入转换流:InputStreamReader,可以把原始的字节流按照指定编码转换成字符输入流。

构造器 说明
public InputStreamReader(InputStream is) 可以把原始的字节流按照代码默认编码转换成字符输入流。几乎不用,与默认的FileReader一样。
public InputStreamReader(InputStream is ,String charset) 可以把原始的字节流按照指定编码转换成字符输入流,这样字符流中的字符就不乱码了(重点)

【示例】

public class InputStreamReaderDemo01 {
    public static void main(String[] args) throws Exception {
        // 代码UTF-8   文件 GBK  "D:\\resources\\data.txt"
        // 1、提取GBK文件的原始字节流。   abc 我
        //                            ooo oo
        InputStream is = new FileInputStream("D:\\resources\\data.txt");
        // 2、把原始字节流转换成字符输入流
        // Reader isr = new InputStreamReader(is); // 默认以UTF-8的方式转换成字符流。 还是会乱码的  跟直接使用FileReader是一样的
        Reader isr = new InputStreamReader(is , "GBK"); // 以指定的GBK编码转换成字符输入流  完美的解决了乱码问题

        BufferedReader br = new BufferedReader(isr);
        String line;
        while ((line = br.readLine()) != null){
            System.out.println(line);
        }
    }
}

3 字符输出转换流

1. 如果需要控制写出去的字符使用的编码,怎么办?

可以把字符以指定编码获取字节后再使用字节输出流写出去:

“我爱你中国”.getBytes(编码)

也可以使用字符输出转换流实现

字符输入转换流:OutputStreamWriter,可以把字节输出流按照指定编码转换成字符输出流。

构造器 说明
public OutputStreamWriter(OutputStream os) 可以把原始的字节输出流按照代码默认编码转换成字符输出流。几乎不用。
public OutputStreamWriter(OutputStream os,String charset) 可以把原始的字节输出流按照指定编码转换成字符输出流(重点)

【示例】

public class OutputStreamWriterDemo02 {
    public static void main(String[] args) throws Exception {
        // 1、定义一个字节输出流
        OutputStream os = new FileOutputStream("io-app2/src/out03.txt");

        // 2、把原始的字节输出流转换成字符输出流
        // Writer osw = new OutputStreamWriter(os); // 以默认的UTF-8写字符出去 跟直接写FileWriter一样
        Writer osw = new OutputStreamWriter(os , "GBK"); // 指定GBK的方式写字符出去

        // 3、把低级的字符输出流包装成高级的缓冲字符输出流。
        BufferedWriter bw = new BufferedWriter(osw);

        bw.write("我爱中国1~~");
        bw.write("我爱中国2~~");
        bw.write("我爱中国3~~");

        bw.close();
    }
}

总结:

1. 字符输出转换流OutputStreamWriter的作用?

● public OutputStreamWriter(OutputStream os,String charset)

● 可以指定编码把字节输出流转换成字符输出流,从而可以指定写出去的字符编码