Java IO - InputStreamReader&OutputStreamWriter

来源:互联网 发布:java 微商城 优惠券 编辑:程序博客网 时间:2024/04/27 23:07

基本概念

  • 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