java io系列21之 InputStreamReader和OutputStreamWriter

简介: InputStreamReader和OutputStreamWriter 是字节流通向字符流的桥梁:它使用指定的 charset 读写字节并将其解码为字符。InputStreamReader 的作用是将“字节输入流”转换成“字符输入流”。

InputStreamReader和OutputStreamWriter 是字节流通向字符流的桥梁:它使用指定的 charset 读写字节并将其解码为字符。
InputStreamReader 的作用是将“字节输入流”转换成“字符输入流”。它继承于Reader。
OutputStreamWriter 的作用是将“字节输出流”转换成“字符输出流”。它继承于Writer。

转载请注明出处:http://www.cnblogs.com/skywang12345/p/io_21.html

更多内容请参考:java io系列01之 "目录"

InputStreamReader和OutputStreamWriter源码分析

1. InputStreamReader 源码(基于jdk1.7.40)

复制代码
 1 package java.io;
 2 
 3 import java.nio.charset.Charset;  4 import java.nio.charset.CharsetDecoder;  5 import sun.nio.cs.StreamDecoder;  6  7  8 // 将“字节输入流”转换成“字符输入流”  9 public class InputStreamReader extends Reader { 10 11 private final StreamDecoder sd; 12 13 // 根据in创建InputStreamReader,使用默认的编码 14 public InputStreamReader(InputStream in) { 15 super(in); 16 try { 17 sd = StreamDecoder.forInputStreamReader(in, this, (String)null); // ## check lock object 18 } catch (UnsupportedEncodingException e) { 19 // The default encoding should always be available 20 throw new Error(e); 21  } 22  } 23 24 // 根据in创建InputStreamReader,使用编码charsetName(编码名) 25 public InputStreamReader(InputStream in, String charsetName) 26 throws UnsupportedEncodingException 27  { 28 super(in); 29 if (charsetName == null) 30 throw new NullPointerException("charsetName"); 31 sd = StreamDecoder.forInputStreamReader(in, this, charsetName); 32  } 33 34 // 根据in创建InputStreamReader,使用编码cs 35 public InputStreamReader(InputStream in, Charset cs) { 36 super(in); 37 if (cs == null) 38 throw new NullPointerException("charset"); 39 sd = StreamDecoder.forInputStreamReader(in, this, cs); 40  } 41 42 // 根据in创建InputStreamReader,使用解码器dec 43 public InputStreamReader(InputStream in, CharsetDecoder dec) { 44 super(in); 45 if (dec == null) 46 throw new NullPointerException("charset decoder"); 47 sd = StreamDecoder.forInputStreamReader(in, this, dec); 48  } 49 50 // 获取解码器 51 public String getEncoding() { 52 return sd.getEncoding(); 53  } 54 55 // 读取并返回一个字符 56 public int read() throws IOException { 57 return sd.read(); 58  } 59 60 // 将InputStreamReader中的数据写入cbuf中,从cbuf的offset位置开始写入,写入长度是length 61 public int read(char cbuf[], int offset, int length) throws IOException { 62 return sd.read(cbuf, offset, length); 63  } 64 65 // 能否从InputStreamReader中读取数据 66 public boolean ready() throws IOException { 67 return sd.ready(); 68  } 69 70 // 关闭InputStreamReader 71 public void close() throws IOException { 72 sd.close(); 73 } 74 }
复制代码

2. OutputStreamWriter 源码(基于jdk1.7.40)

复制代码
 1 package java.io;
 2 
 3 import java.nio.charset.Charset;  4 import java.nio.charset.CharsetEncoder;  5 import sun.nio.cs.StreamEncoder;  6  7 // 将“字节输出流”转换成“字符输出流”  8 public class OutputStreamWriter extends Writer {  9 10 private final StreamEncoder se; 11 12 // 根据out创建OutputStreamWriter,使用编码charsetName(编码名) 13 public OutputStreamWriter(OutputStream out, String charsetName) 14 throws UnsupportedEncodingException 15  { 16 super(out); 17 if (charsetName == null) 18 throw new NullPointerException("charsetName"); 19 se = StreamEncoder.forOutputStreamWriter(out, this, charsetName); 20  } 21 22 // 根据out创建OutputStreamWriter,使用默认的编码 23 public OutputStreamWriter(OutputStream out) { 24 super(out); 25 try { 26 se = StreamEncoder.forOutputStreamWriter(out, this, (String)null); 27 } catch (UnsupportedEncodingException e) { 28 throw new Error(e); 29  } 30  } 31 32 // 根据out创建OutputStreamWriter,使用编码cs 33 public OutputStreamWriter(OutputStream out, Charset cs) { 34 super(out); 35 if (cs == null) 36 throw new NullPointerException("charset"); 37 se = StreamEncoder.forOutputStreamWriter(out, this, cs); 38  } 39 40 // 根据out创建OutputStreamWriter,使用编码器enc 41 public OutputStreamWriter(OutputStream out, CharsetEncoder enc) { 42 super(out); 43 if (enc == null) 44 throw new NullPointerException("charset encoder"); 45 se = StreamEncoder.forOutputStreamWriter(out, this, enc); 46 }java io系列01之 "目录" 47 48 // 获取编码器enc 49 public String getEncoding() { 50 return se.getEncoding(); 51  } 52 53 // 刷新缓冲区 54 void flushBuffer() throws IOException { 55  se.flushBuffer(); 56  } 57 58 // 将单个字符写入到OutputStreamWriter中 59 public void write(int c) throws IOException { 60  se.write(c); 61  } 62 63 // 将字符数组cbuf从off开始的数据写入到OutputStreamWriter中,写入长度是len 64 public void write(char cbuf[], int off, int len) throws IOException { 65  se.write(cbuf, off, len); 66  } 67 68 // 将字符串str从off开始的数据写入到OutputStreamWriter中,写入长度是len 69 public void write(String str, int off, int len) throws IOException { 70  se.write(str, off, len); 71 }java io系列01之 "目录" 72 73 // 刷新“输出流” 74 // 它与flushBuffer()的区别是:flushBuffer()只会刷新缓冲,而flush()是刷新流,flush()包括了flushBuffer。 75 public void flush() throws IOException { 76 se.flush(); 77 } 78 79 // 关闭“输出流” 80 public void close() throws IOException { 81 se.close(); 82 } 83 }
复制代码

说明

OutputStreamWriter 作用和原理都比较简单。
作用就是将“字节输出流”转换成“字符输出流”。它的原理是,我们创建“字符输出流”对象时,会指定“字节输出流”以及“字符编码”。

 

示例程序

InputStreamReader和OutputStreamWriter的使用示例,参考源码(StreamConverter.java):

复制代码
 1 import java.io.File;
 2 import java.io.FileInputStream;  3 import java.io.FileOutputStream;  4 import java.io.OutputStreamWriter;;  5 import java.io.InputStreamReader;  6 import java.io.IOException;  7  8 /**  9  * InputStreamReader 和 OutputStreamWriter 测试程序 10  * 11  * @author skywang 12 */ 13 public class StreamConverter { 14 15 private static final String FileName = "file.txt"; 16 private static final String CharsetName = "utf-8"; 17 //private static final String CharsetName = "gb2312"; 18 19 public static void main(String[] args) { 20  testWrite(); 21  testRead(); 22  } 23 24 /** 25  * OutputStreamWriter 演示函数 26  * 27 */ 28 private static void testWrite() { 29 try { 30 // 创建文件“file.txt”对应File对象 31 File file = new File(FileName); 32 // 创建FileOutputStream对应OutputStreamWriter:将字节流转换为字符流,即写入out1的数据会自动由字节转换为字符。 33 OutputStreamWriter out1 = new OutputStreamWriter(new FileOutputStream(file), CharsetName); 34 // 写入10个汉字 35 out1.write("字节流转为字符流示例"); 36 // 向“文件中”写入"0123456789"+换行符 37 out1.write("0123456789\n"); 38 39  out1.close(); 40 41 } catch(IOException e) { 42  e.printStackTrace(); 43  } 44  } 45 46 /** 47  * InputStreamReader 演示程序 48 */ 49 private static void testRead() { 50 try { 51 // 方法1:新建FileInputStream对象 52 // 新建文件“file.txt”对应File对象 53 File file = new File(FileName); 54 InputStreamReader in1 = new InputStreamReader(new FileInputStream(file), CharsetName); 55 56 // 测试read(),从中读取一个字符 57 char c1 = (char)in1.read(); 58 System.out.println("c1="+c1); 59 60 // 测试skip(long byteCount),跳过4个字符 61 in1.skip(6); 62 63 // 测试read(char[] cbuf, int off, int len) 64 char[] buf = new char[10]; 65 in1.read(buf, 0, buf.length); 66 System.out.println("buf="+(new String(buf))); 67 68  in1.close(); 69 } catch(IOException e) { 70  e.printStackTrace(); 71  } 72  } 73 }
复制代码

运行结果
c1=字
buf=流示例0123456
结果说明
(01) testWrite() 的作用是将“内容写入到输出流”。写入的时候,会将写入的内容转换utf-8编码并写入。
(02) testRead() 的作用是将“内容读取到输入流”。读取的时候,会将内容转换成utf-8的内容转换成字节并读出来。
生成的文件utf-8的file.txt的16进制效果图如下:

将StreamConverter.java中的CharsetName修改为"gb2312"。运行程序,生产的file.txt的16进制效果图如下:

 

相关文章
|
21天前
|
Java
java 中 IO 流
Java中的IO流是用于处理输入输出操作的机制,主要包括字节流和字符流两大类。字节流以8位字节为单位处理数据,如FileInputStream和FileOutputStream;字符流以16位Unicode字符为单位,如FileReader和FileWriter。这些流提供了读写文件、网络传输等基本功能。
40 9
|
2月前
|
存储 缓存 Java
java基础:IO流 理论与代码示例(详解、idea设置统一utf-8编码问题)
这篇文章详细介绍了Java中的IO流,包括字符与字节的概念、编码格式、File类的使用、IO流的分类和原理,以及通过代码示例展示了各种流的应用,如节点流、处理流、缓存流、转换流、对象流和随机访问文件流。同时,还探讨了IDEA中设置项目编码格式的方法,以及如何处理序列化和反序列化问题。
88 1
java基础:IO流 理论与代码示例(详解、idea设置统一utf-8编码问题)
|
2月前
|
Java 数据处理 开发者
揭秘Java IO流:字节流与字符流的神秘面纱!
揭秘Java IO流:字节流与字符流的神秘面纱!
39 1
|
2月前
|
自然语言处理 Java 数据处理
Java IO流全解析:字节流和字符流的区别与联系!
Java IO流全解析:字节流和字符流的区别与联系!
97 1
|
3月前
|
Java 大数据 API
Java 流(Stream)、文件(File)和IO的区别
Java中的流(Stream)、文件(File)和输入/输出(I/O)是处理数据的关键概念。`File`类用于基本文件操作,如创建、删除和检查文件;流则提供了数据读写的抽象机制,适用于文件、内存和网络等多种数据源;I/O涵盖更广泛的输入输出操作,包括文件I/O、网络通信等,并支持异常处理和缓冲等功能。实际开发中,这三者常结合使用,以实现高效的数据处理。例如,`File`用于管理文件路径,`Stream`用于读写数据,I/O则处理复杂的输入输出需求。
238 12
|
2月前
|
Java
Java 中 IO 流的分类详解
【10月更文挑战第10天】不同类型的 IO 流具有不同的特点和适用场景,我们可以根据具体的需求选择合适的流来进行数据的输入和输出操作。在实际应用中,还可以通过组合使用多种流来实现更复杂的功能。
63 0
|
2月前
|
存储 Java 程序员
【Java】文件IO
【Java】文件IO
39 0
|
4月前
|
存储 Java
【IO面试题 四】、介绍一下Java的序列化与反序列化
Java的序列化与反序列化允许对象通过实现Serializable接口转换成字节序列并存储或传输,之后可以通过ObjectInputStream和ObjectOutputStream的方法将这些字节序列恢复成对象。
|
5月前
|
Java 大数据
解析Java中的NIO与传统IO的区别与应用
解析Java中的NIO与传统IO的区别与应用
|
4月前
|
Java 数据处理
Java IO 接口(Input)究竟隐藏着怎样的神秘用法?快来一探究竟,解锁高效编程新境界!
【8月更文挑战第22天】Java的输入输出(IO)操作至关重要,它支持从多种来源读取数据,如文件、网络等。常用输入流包括`FileInputStream`,适用于按字节读取文件;结合`BufferedInputStream`可提升读取效率。此外,通过`Socket`和相关输入流,还能实现网络数据读取。合理选用这些流能有效支持程序的数据处理需求。
51 2