Hey, Nice to meet You. 

节.人情有所不能忍者,匹夫见辱,拔剑而起,挺身而斗,此不足为勇也,天下有大勇者,猝然临之而不惊,无故加之而不怒.此其所挟持者甚大,而其志甚远也.          ☆☆☆所谓豪杰之士,必有过人之

Java IO流详解(六)----转换流(字节流和字符流之间的转换)

转换流也是一种处理流,它提供了字节流和字符流之间的转换。在Java IO流中提供了两个转换流:InputStreamReader 和 OutputStreamWriter,这两个类都属于字符流。其中InputStreamReader将字节输入流转为字符输入流,继承自Reader。OutputStreamWriter是将字符输出流转为字节输出流,继承自Writer。

 

众所周知,计算机中存储的数据都是二进制的数字,我们在电脑屏幕上看到的文字信息是将二进制转换之后显示的,两者之间存在编码解码的过程,其互相转换必须遵循某种规则,即编码和解码都遵循同一种规则才能将文字信息正常显示,如果编码跟解码使用了不同的规则,就会出现乱码的情况。

  • 编码:字符、字符串(能看懂的)--字节(看不懂的)
  • 解码:字节(看不懂的)-->字符、字符串(能看懂的)

 

上面说的编码与解码的过程需要遵循某种规则,这种规则就是不同的字符编码。我们在刚刚学习编程的时候最早接触就是ASCII码,它主要是用来显示英文和一些符号,到后面还有接触到别的编码规则常用的有:gb2312,gbk,utf-8等。它们分别属于不同的编码集。

我们需要明确的是字符编码和字符集是两个不同层面的概念。

  • encoding是charset encoding的简写,即字符集编码,简称编码
  • charset是character set的简写,即字符集

编码是依赖于字符集的,一个字符集可以有多个编码实现,就像代码中的接口实现依赖于接口一样。

转换流的原理是:字符流 = 字节流 + 编码表。在转换流中选择正确的编码非常的重要,因为指定了编码,它所对应的字符集自然就指定了,否则很容易出现乱码,所以编码才是我们最终要关心的。

转换流的特点:其是字符流和字节流之间的桥梁。

       可对读取到的字节数据经过指定编码转换成字符

       可对读取到的字符数据经过指定编码转换成字节

那么何时使用转换流?

       当字节和字符之间有转换动作时

       流操作的数据需要编码或解码时

 

1、InputStreamReader

InputStreamReader是字节流到字符流的桥梁:它读取字节,并使用指定的字符集将其解码为字符。它的字符集可以由名称指定,也可以接受平台的默认字符集。

构造方法:

  • InputStreamReader(InputStream in):创建一个默认字符集字符输入流。
  • InputStreamReader(InputStream in, String charsetName):创建一个指定字符集的字符流。

构造方法示例代码:

    InputStreamReader isr1 = new InputStreamReader(new FileInputStream("D:\\IO\\utf8.txt"));
    InputStreamReader isr2 = new InputStreamReader(new FileInputStream("D:\\IO\\utf8.txt"),"UTF-8");

InputStreamReader读入不同编码举例(读入的文件编码是UTF-8):

复制代码
package com.thr;

import java.io.*;

/**
 * @author Administrator
 * @date 2020-02-27
 * @desc InputStreamReader
 */
public class InputStreamReaderTest {
    public static void main(String[] args) {
        //定义转换流
        InputStreamReader isr = null;
        InputStreamReader isr1 = null;

        try {
            //创建流对象,默认编码方式
            isr = new InputStreamReader(new FileInputStream("D:\\IO\\utf8.txt"));
            //创建流对象,指定GBK编码
            isr1 = new InputStreamReader(new FileInputStream("D:\\IO\\utf8.txt"),"GBK");

            //默认方式打印
            int len;
            char[] buffer = new char[1024];
            while ((len=isr.read(buffer))!=-1){
                System.out.println(new String(buffer,0,len));
            }
            //GBK编码方式打印
            int len1;
            char[] buffer1 = new char[1024];
            while ((len1=isr1.read(buffer1))!=-1){
                System.out.println(new String(buffer1,0,len1));
            }

            System.out.println("成功...");
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //释放资源,先使用的后关闭
            if (isr1!=null){
                try {
                    isr1.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (isr!=null){
                try {
                    isr.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}
//运行结果:
--UTF-8
武汉加油
中国加油
齐心协力
战胜疫情
--GBK
锘挎姹夊姞娌�
涓浗鍔犳补
榻愬績鍗忓姏
鎴樿儨鐤儏
复制代码

可以发现,UTF-8编码没有出现乱码,而GBK编码出现了乱码,这是因为是在IDEA编辑器下打印的,我的IDEA编辑器设置的默认编码是UTF-8。而UTF-8的编码集是Unicode,GBK的编码集是GBK,两者并没有通过转换,所以GBK编码在Unicode集上打印出现了乱码。

 

2、OutputStreamWriter

OutputStreamWriter是字符流通向字节流的桥梁:用指定的字符集将字符编码为字节。它的字符集可以由名称指定,也可以接受平台的默认字符集。

构造方法:

  • OutputStreamWriter(OutputStream in): 创建一个使用默认字符集的字符流。
  • OutputStreamWriter(OutputStream in, String charsetName): 创建一个指定字符集的字符流。

构造方法示例代码:

    OutputStreamWriter isr1 = new OutputStreamWriter(new FileOutputStream("D:\\IO\\gbk.txt""));
    OutputStreamWriter isr2 = new OutputStreamWriter(new FileOutputStream("D:\\IO\\gbk1.txt") , "GBK");

OutputStreamWriter读出不同编码举例:

复制代码
package com.thr;

import java.io.*;

/**
 * @author Administrator
 * @date 2020-02-27
 * @desc OutputStreamWriter
 */
public class OutputStreamReaderTest {
    public static void main(String[] args) {
        //定义转换流
        OutputStreamWriter osw = null;
        OutputStreamWriter osw1 = null;

        try {
            osw = new OutputStreamWriter(new FileOutputStream("D:\\IO\\gbk.txt"));
            osw1 = new OutputStreamWriter(new FileOutputStream("D:\\IO\\gbk1.txt"),"GBK");
            //以默认格式写出
            osw.write("武汉加油,中国加油");
            //以GBK格式写出
            osw1.write("武汉加油,中国加油");

            System.out.println("成功...");
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //释放资源,先使用的后关闭
            if (osw1!=null){
                try {
                    osw1.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (osw!=null){
                try {
                    osw.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}
复制代码

我们运行完后发现并没有乱码,这是因为Windows系统默认支持了UTF-8和GBK字符集。可以将输出的路径改为当前项目下 new FileOutputStream(“gbk.txt”);然后用Idea打开就可以看成差别来了。

 

3、转换文件编码

将UTF-8编码的文本文件,转换为GBK编码的文本文件。

    1、指定UTF-8编码的转换流,读取文本文件。

    2、使用GBK编码的转换流,写出文本文件。

image

复制代码
package com.thr;

import java.io.*;

/**
 * @author Administrator
 * @date 2020-02-27
 * @desc 将读入UTF-8文件转换为GBK
 */
public class ConversionStreamTest {

    public static void main(String[] args) {
        //定义转换流
        InputStreamReader isr = null;
        OutputStreamWriter osw = null;

        try {
            //创建流对象,指定GBK编码
            isr = new InputStreamReader(new FileInputStream("D:\\IO\\utf8.txt"),"UTF-8");
            osw = new OutputStreamWriter(new FileOutputStream("gbk.txt"),"GBK");

            int len;
            char[] buffer = new char[1024];
            while ((len=isr.read(buffer))!=-1){
                osw.write(buffer,0,len);
            }
            System.out.println("成功...");
        }  catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //释放资源
            if (osw!=null){
                try {
                    osw.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (isr!=null){
                try {
                    isr.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}
复制代码
posted @   唐浩荣  阅读(5502)  评论(2编辑  收藏  举报
编辑推荐:
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
阅读排行:
· 使用C#创建一个MCP客户端
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示

目录导航