string编码格式转换_转换流

字符流回顾 字符流:字节流+编码表

2cd1ba543c14e9a310f33e4604e899da.png

InputStreamReader是从字节流到字符流的桥梁:它读取字节,并使用指定的charset(编码表)将其解码为字符。它使用的字符集可以由名称指定,也可以被明确指定,或者可以接受平台的默认字符集。说白了它就是用来将字符流和字节流之间做了一个转换而已。
OutputStreamWriter是从字符流到字节流的桥梁:使用指定的charset(编码表)将写入的字符编码为字节。它使用的字符集可以由名称指定,也可以被明确指定,或者可以接受平台默认的字符集。说白了它就是用来将字符和字节这两者之间做了个转换。

下图的解释:
首先我在本地有一个文件,现在我要用FileReader去读取它。因为FileReader它底层是字节流+编码表的形式,所以实际上还是用字节流去读取的,所以一开始是字节流,然后呢通过中间的InputStreamReader它会把字节流转换成FileReader,这时候才会到内存当中,而它中间转换的格式会按照我们指定的编码表来进行转换。当它要往外写时就会用到FileWrite往外写,但是在底层它也会通过OutputStreamWriter转换成字节流再写到本地文件中去。
右边这个OutputStreamWriter就是用来把字符流转换成字节流,
而左边那个InputStreamReader就是用来将字节流转换为字符流。

0f505f5f1b3557f854021e7e7e0c9bba.png

转换流的使用场景
在JDK11之前,转换流可以用作指定编码读写,在DJK11以后,一般不会直接去操作转换流了。

下面这串代码为什么会出现乱码?

public class ConvertedDemo1 {
    public static void main(String[] args) throws IOException {
        //a.txt内部存储着五个汉字,连起来是:冬马是小三

        /*
        这个方法直接读取会产生乱码
        因为文件是GBK码表
        而idea默认是UTF-8编码格式
        所以两者不一致,导致乱码
         */
        FileReader fr = new FileReader("D:a.txt");
        int ch;
        while((ch = fr.read()) != -1){
            System.out.print((char)ch);
        }
        fr.close();
    }
}

60cb326c45f4e90fc3d157af7364e384.png
输出结构为什么是乱码?

因为记事本默认码表是ANSI,而idea默认码表是UTF-8,这两者之间的码表不一致,所以有冲突,最后就会输出乱码。想要得到正确输出的方式是改变记事本或idea的默认编码。(一般改变记事本的默认编码)

b1920392b62785c471e5d732159df3bd.png
记事本的默认编码是ANSI

cb31b013b59e940891bc42e770e16c3f.png
修改记事本默认编码后的输出结果,但是请注意,最前面有个小横杠

如何用代码解决此问题?
使用转换流解决,第一个参数传递一个字节流,第二个参数传递字符集名称(charsetName)(可省略)。

public class ConvertedDemo1 {
    public static void main(String[] args) throws IOException {
        //a.txt内部存储着五个汉字,连起来是:冬马是小三
        /**
         * 如何解决乱码现象?
         * 文件是什么码表,那么咱们就必须使用什么码表去读取。
         * 那么我们就要指定使用GBK码表去读取文件
         */
//        第一个参数写字节输入流,第二个参数写编码方式
        InputStreamReader isr = new InputStreamReader(new FileInputStream("D:a.txt"),"GBK");
        int ch;
        while((ch = isr.read()) != -1){
            System.out.print((char)ch);
        }
        isr.close();
    }
}

向外写

public class ConvertedDemo1 {
    public static void main(String[] args) throws IOException 
//        第一个参数写字节输出流,第二个参数写编码方式
        OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("D:b.txt"),"utf-8");
        osw.write("她也是我的心上人");
        osw.close();
    }
}

问:1:为什么向外写时指定了编码格式为UTF-8,但用记事本打开时却不显示乱码?
因为window系统会自动用UTF-8去读取。
问题2:打开记事本将它用ANSI格式打开会报错了?
答:不会,因为记事本这个软件会自动使用正确的格式将它打开。(这跟代码无关)


JDK11可以不用转换流而使用FileReader这个类,下面这段代码应该能用,但我没测试过。。。

public class ConvertedDemo1 {
    public static void main(String[] args) throws IOException {
        //a.txt内部存储着五个汉字,连起来是:冬马是小三
        FileReader fr = new FileReader("D:a.txt", Charset.forName("gbk"));
        int ch;
        while((ch = fr.read()) != -1){
            System.out.print((char)ch);
        }
        fr.close();
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值