Java IO - InputStreamReader&OutputStreamWriter

基本概念

  • InputStreamReader / OutputStreamWriter 这两个类分别继承了 ReaderWriter,它们提供了从字节流到字符流的转换。

  • 在转换的过程中,既可以使用平台默认的字符编码也可以手动指定。如果需要更多地控制编码过程,则应该使用 CharsetEncoder 类。

  • 真正负责转换工作的是 StreamDecoder


实例探究

下面先来一个简单使用例子

public class Test {

    private static final String TEMPFILE = "E:" + File.separator + "1.txt";

    public static void main(String[] args) throws Exception {
        writer(TEMPFILE);
        read(TEMPFILE);
        // 输出内容:你好
    }

    private static void read(String path) throws Exception {
        File file = new File(path);
        Reader reader = new InputStreamReader(new FileInputStream(file));
        char[] buffer = new char[1024];
        int count = 0;
        while ((count = reader.read(buffer)) != -1) {
            System.out.println(new String(buffer, 0, count));
        }
    }

    private static void writer(String path) throws IOException {
        File file = new File(path);
        Writer writer = new OutputStreamWriter(new FileOutputStream(file), "UTF-8");
        writer.write("你好");
        writer.close();

    }
}

源码分析

1.InputStreamReader

类结构图

这里写图片描述

成员变量

//从字节到字符的转换真正依靠的是这个类
private final StreamDecoder sd;

关于构造函数,发现该类总共定义了 4 个构造函数。关于 ②③ 的方式其实差不多,因为通过下面的例子可以清楚看到 charsetName 与 Charset 关系。

String charsetName ="UTF-8";
Charset  = Charset.forName(charsetName);

观察代码会发现其实真正负责转换工作的是 StreamDecoder 类中的 forInputStreamReader 方法,这里只是简单的调用了这个方法而已。

//①构造函数,使用默认的字符集
public InputStreamReader(InputStream in) {
    super(in);
    try {
        sd = StreamDecoder.forInputStreamReader(in, this, (String) null); 
    } catch (UnsupportedEncodingException e) {
        // The default encoding should always be available
        throw new Error(e);
    }
}

//②构造函数,使用指定的字符集名称
public InputStreamReader(InputStream in, String charsetName) throws UnsupportedEncodingException {
    super(in);
    if (charsetName == null)
        throw new NullPointerException("charsetName");
    sd = StreamDecoder.forInputStreamReader(in, this, charsetName);
}

//②构造函数,使用指定的字符集
public InputStreamReader(InputStream in, Charset cs) {
    super(in);
    if (cs == null)
        throw new NullPointerException("charset");
    sd = StreamDecoder.forInputStreamReader(in, this, cs);
}

//④构造函数,使用给定字符集解码器
public InputStreamReader(InputStream in, CharsetDecoder dec) {
    super(in);
    if (dec == null)
        throw new NullPointerException("charset decoder");
    sd = StreamDecoder.forInputStreamReader(in, this, dec);
}

剩余方法, 发现实现的核心都是围绕着 StreamDecoder 类。

public String getEncoding() {
    return sd.getEncoding();
}

public int read() throws IOException {
    return sd.read();
}

public int read(char cbuf[], int offset, int length) throws IOException {
    return sd.read(cbuf, offset, length);
}

public boolean ready() throws IOException {
    return sd.ready();
}

public void close() throws IOException {
    sd.close();
}

2.OutputStreamWriter

结构图

这里写图片描述

成员变量,同上,这里不再阐述

同样的定义了 4 个构造函数

public OutputStreamWriter(OutputStream out) {
    super(out);
    try {
        se = StreamEncoder.forOutputStreamWriter(out, this, (String) null);
    } catch (UnsupportedEncodingException e) {
        throw new Error(e);
    }
}

public OutputStreamWriter(OutputStream out, String charsetName) throws UnsupportedEncodingException {
    super(out);
    if (charsetName == null){
        throw new NullPointerException("charsetName");
    }
    se = StreamEncoder.forOutputStreamWriter(out, this, charsetName);
}

public OutputStreamWriter(OutputStream out, Charset cs) {
    super(out);
    if (cs == null){
        throw new NullPointerException("charset");
    }
    se = StreamEncoder.forOutputStreamWriter(out, this, cs);
}

public OutputStreamWriter(OutputStream out, CharsetEncoder enc) {
    super(out);
    if (enc == null){
        throw new NullPointerException("charset encoder");
    }   
    se = StreamEncoder.forOutputStreamWriter(out, this, enc);
}

剩余的方法

public String getEncoding() {
    return se.getEncoding();
}

//刷新输出缓冲数组到底层系统(不是刷新流本身),这是不设置为私有方法,是为让 PrintStream 能调用到
void flushBuffer() throws IOException {
    se.flushBuffer();
}

public void write(int c) throws IOException {
    se.write(c);
}

public void write(char cbuf[], int off, int len) throws IOException {
    se.write(cbuf, off, len);
}

public void write(String str, int off, int len) throws IOException {
    se.write(str, off, len);
}

public void flush() throws IOException {
    se.flush();
}

public void close() throws IOException {
    se.close();
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

oxf

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值