A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

今天学习InputStreamReader与OutputStreamWriter。

InputStreamReader,字节流通向字符流的桥梁:它使用指定的charset读取字节并将其解码为字符。

OutputStreamWriter,字符流通向字节流的桥梁:它使用指定的charset将要写入流中的字符编码成字节。

InputStreamReader

每次调用InputStreamReader中的read方法都会导致从底层输入流读取一个或多个字节,然后调用编码转换器将字节转化为字符。为避免频繁调用转换器,实现从字节到字符的高效转换,可以提前从底层流读取更多的字节。

为了达到最高效率,可要考虑在BufferedReader内包装InputStreamReader。例如:
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));

public class InputStreamReader extends Reader {    //InputStreamReader的功能是依赖StreamDecoder完成的。    private final StreamDecoder sd;    /**     * 创建一个使用默认字符集的InputStreamReader。     */    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);        }    }    /**     * 创建使用指定字符集的 InputStreamReader。     *     * @exception  UnsupportedEncodingException 如果不支持指定的字符集     */    public InputStreamReader(InputStream in, String charsetName)        throws UnsupportedEncodingException    {        super(in);        if (charsetName == null)            throw new NullPointerException("charsetName");        sd = StreamDecoder.forInputStreamReader(in, this, charsetName);    }    /**     * 创建使用给定字符集的InputStreamReader。     */    public InputStreamReader(InputStream in, Charset cs) {        super(in);        if (cs == null)            throw new NullPointerException("charset");        sd = StreamDecoder.forInputStreamReader(in, this, cs);    }    /**     * 创建使用给定字符集解码器的InputStreamReader。     */    public InputStreamReader(InputStream in, CharsetDecoder dec) {        super(in);        if (dec == null)            throw new NullPointerException("charset decoder");        sd = StreamDecoder.forInputStreamReader(in, this, dec);    }    /**     * 返回此流使用的字符编码的名称。     * 如果该编码有历史上用过的名称,则返回该名称;否则返回该编码的规范化名称。     * 如果使用InputStreamReader(InputStream, String)构造方法创建此实例,     * 则返回的由此编码生成的唯一名称可能与传递给该构造方法的名称不一样。     * 如果流已经关闭,则此方法将会返回 null。     *      * @return 此编码的历史名称,如果流已经关闭,则返回null     */    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);    }    /**     * 判断此流是否已经准备好用于读取。     * 如果其输入缓冲区不为空,或者可从底层字节流读取字节,则InputStreamReader已做好被读取准备。     */    public boolean ready() throws IOException {        return sd.ready();    }    //关闭该流并释放与之关联的所有资源。    public void close() throws IOException {        sd.close();    }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
demo/** * InputStreamReader demo * @author panww */public class InputStreamReaderTest {    /**     * inputStreamReader.txt中的内容为“潘威威的博客http://blog.csdn.net/panweiwei1994”     */    @Test    public void test() {        try {            File file = new File("inputStreamReader.txt");            InputStreamReader reader = new InputStreamReader(new FileInputStream(file),"gbk");            System.out.println("ready():"+reader.ready());            System.out.println("getEncoding():"+reader.getEncoding());            System.out.println("read():"+(char)reader.read());            char[] buf = new char[40];            reader.read(buf, 0, buf.length);            System.out.println("read(char[], int, int):"+(new String(buf)));            reader.close();        } catch(IOException e) {            e.printStackTrace();        }    }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31

控制台打印内容为

ready():truegetEncoding():GBKread():潘read(char[], int, int):威威的博客http://blog.csdn.net/panweiwei1994
  • 1
  • 2
  • 3
  • 4
OutputStreamWriter

每次调用write()方法都会导致在给定字符(或字符集)上调用编码转换器。为避免频繁调用转换器,在写入底层输出流之前,可以将得到的这些字节积累在缓冲区。例如,可考虑将OutputStreamWriter包装到BufferedWriter中。

Writer out = new BufferedWriter(new OutputStreamWriter(System.out));

此类总是使用字符集的默认替代序列替代错误代理元素和不可映射的字符序列。如果需要更多地控制编码过程,则应该使用CharsetEncoder 类。

public class OutputStreamWriter extends Writer {    //OutputStreamWriter的功能是依赖于StreamEncoder完成的    private final StreamEncoder se;    /**     * 创建使用默认字符编码的OutputStreamWriter。     */    public OutputStreamWriter(OutputStream out, String charsetName)        throws UnsupportedEncodingException    {        super(out);        if (charsetName == null)            throw new NullPointerException("charsetName");        se = StreamEncoder.forOutputStreamWriter(out, this, charsetName);    }    /**     * 创建使用给定字符集的OutputStreamWriter。     */    public OutputStreamWriter(OutputStream out) {        super(out);        try {            se = StreamEncoder.forOutputStreamWriter(out, this, (String)null);        } catch (UnsupportedEncodingException e) {            throw new Error(e);        }    }    /**     * 创建使用给定字符集的OutputStreamWriter。     */    public OutputStreamWriter(OutputStream out, Charset cs) {        super(out);        if (cs == null)            throw new NullPointerException("charset");        se = StreamEncoder.forOutputStreamWriter(out, this, cs);    }    /**     * 创建使用给定字符集编码器的OutputStreamWriter。     */    public OutputStreamWriter(OutputStream out, CharsetEncoder enc) {        super(out);        if (enc == null)            throw new NullPointerException("charset encoder");        se = StreamEncoder.forOutputStreamWriter(out, this, enc);    }    /**     * 返回此流使用的字符编码的名称。     * 如果该编码具有历史名称,则返回该名称;否则返回该编码的规范化名称。     * 如果此实例是用OutputStreamWriter(OutputStream, String)构造方法创建的,     * 则返回的对于编码唯一的名称可能与传递给该构造方法的名称不同。     * 如果流已经关闭,则此方法可能返回 null。     */    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();    }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
demoimport java.io.File;import java.io.FileOutputStream;import java.io.IOException;import java.io.OutputStreamWriter;import org.junit.Test;/** * OutputStreamWriter Demo *  * @author panww */public class OutputStreamWriterTest {    @Test    public void test() {        try {            File file = new File("inputStreamReader.txt");            OutputStreamWriter out1 = new OutputStreamWriter(new FileOutputStream(file));            out1.write("潘威威的博客");            out1.close();        } catch (IOException e) {            e.printStackTrace();        }    }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27

运行后,inputStreamReader.txt中的内容为潘威威的博客。

总结
  • InputStreamReader,字节流通向字符流的桥梁:它使用指定的charset读取字节并将其解码为字符。
  • 每次调用InputStreamReader中的read方法都会导致从底层输入流读取一个或多个字节,然后调用编码转换器将字节转化为字符。为避免频繁调用转换器,实现从字节到字符的高效转换,可以提前从底层流读取更多的字节。为了达到最高效率,可要考虑在BufferedReader内包装InputStreamReader。
  • InputStreamReader的功能是依赖于StreamDecoder完成的。
  • OutputStreamWriter,字符流通向字节流的桥梁:它使用指定的charset将要写入流中的字符编码成字节。
  • 每次调用write()方法都会导致在给定字符(或字符集)上调用编码转换器。为避免频繁调用转换器,在写入底层输出流之前,可以将得到的这些字节积累在缓冲区。例如,可考虑将OutputStreamWriter包装到BufferedWriter中。

关于InputStreamReader与OutputStreamWriter就讲到这里,想了解更多内容请参考

版权声明


1 个回复

倒序浏览

很不错,受教了
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马