(八)InputStreamReader及OutputStreamWriter

InputStreamReader的作用就是将字节输入流变为字符输入流,底层的实现是靠StreamDecoder完成的。

public class InputStreamReader extends Reader {

    private final StreamDecoder sd;


    public InputStreamReader(InputStream in) {
        super(in);
        try {
            sd = StreamDecoder.forInputStreamReader(in, this, (String)null); // ## check lock object
        } 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);
    }


    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();
    }
}

StreamDecoder在jdk源码中并没有开源,不过通过相应版本的openJDK可以看到StreamDecoder的源码。

public int read() throws IOException {
        return read0();
    }
//读取单个字符
private int read0() throws IOException {
        synchronized (lock) {

            // Return the leftover char, if there is one
            if (haveLeftoverChar) {
                haveLeftoverChar = false;
                return leftoverChar;
            }

            // Convert more bytes
            char cb[] = new char[2];//至少读取2个字符
            int n = read(cb, 0, 2);
            switch (n) {
            case -1:
                return -1;
            case 2://保留多读取的字符,以便下次使用
                leftoverChar = cb[1];
                haveLeftoverChar = true;
                // FALL THROUGH
            case 1://返回读取到的第一个字符
                return cb[0];
            default:
                assert false : n;
                return -1;
            }
        }
    }
//读取字符数组
public int read(char cbuf[], int offset, int length) throws IOException {
        int off = offset;
        int len = length;
        synchronized (lock) {
            ensureOpen();
            if ((off < 0) || (off > cbuf.length) || (len < 0) ||
                ((off + len) > cbuf.length) || ((off + len) < 0)) {
                throw new IndexOutOfBoundsException();
            }
            if (len == 0)
                return 0;

            int n = 0;
            //返回此前缓存的单个字符
            if (haveLeftoverChar) {
                // Copy the leftover char into the buffer
                cbuf[off] = leftoverChar;
                off++; len--;
                haveLeftoverChar = false;
                n = 1;
                if ((len == 0) || !implReady())
                    // Return now if this is all we can produce w/o blocking
                    return n;
            }
            //读取单个字符
            if (len == 1) {
                // Treat single-character array reads just like read()
                int c = read0();
                if (c == -1)
                    return (n == 0) ? -1 : n;
                cbuf[off] = (char)c;
                return n + 1;
            }

            return n + implRead(cbuf, off, off + len);//读取底层输入流的函数
        }
    }

在read函数中,要求至少读取2个字符,为什么这样设置呢?这跟Unicode字符集及utf-16编码有关了,具体解释可以参考Character的API文档及参考文章使用 Java 语言进行 Unicode 代理编程


OutputStreamWriter使用StreamEncoder进行字符到字节的编码,原理与上面类似。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值