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)

 package java.io;

 import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;
import sun.nio.cs.StreamDecoder; // 将“字节输入流”转换成“字符输入流”
public class InputStreamReader extends Reader { private final StreamDecoder sd; // 根据in创建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);
}
} // 根据in创建InputStreamReader,使用编码charsetName(编码名)
public InputStreamReader(InputStream in, String charsetName)
throws UnsupportedEncodingException
{
super(in);
if (charsetName == null)
throw new NullPointerException("charsetName");
sd = StreamDecoder.forInputStreamReader(in, this, charsetName);
} // 根据in创建InputStreamReader,使用编码cs
public InputStreamReader(InputStream in, Charset cs) {
super(in);
if (cs == null)
throw new NullPointerException("charset");
sd = StreamDecoder.forInputStreamReader(in, this, cs);
} // 根据in创建InputStreamReader,使用解码器dec
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();
} // 将InputStreamReader中的数据写入cbuf中,从cbuf的offset位置开始写入,写入长度是length
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();
} // 关闭InputStreamReader
public void close() throws IOException {
sd.close();
}
}

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

 package java.io;

 import java.nio.charset.Charset;
import java.nio.charset.CharsetEncoder;
import sun.nio.cs.StreamEncoder; // 将“字节输出流”转换成“字符输出流”
public class OutputStreamWriter extends Writer { private final StreamEncoder se; // 根据out创建OutputStreamWriter,使用编码charsetName(编码名)
public OutputStreamWriter(OutputStream out, String charsetName)
throws UnsupportedEncodingException
{
super(out);
if (charsetName == null)
throw new NullPointerException("charsetName");
se = StreamEncoder.forOutputStreamWriter(out, this, charsetName);
} // 根据out创建OutputStreamWriter,使用默认的编码
public OutputStreamWriter(OutputStream out) {
super(out);
try {
se = StreamEncoder.forOutputStreamWriter(out, this, (String)null);
} catch (UnsupportedEncodingException e) {
throw new Error(e);
}
} // 根据out创建OutputStreamWriter,使用编码cs
public OutputStreamWriter(OutputStream out, Charset cs) {
super(out);
if (cs == null)
throw new NullPointerException("charset");
se = StreamEncoder.forOutputStreamWriter(out, this, cs);
} // 根据out创建OutputStreamWriter,使用编码器enc
public OutputStreamWriter(OutputStream out, CharsetEncoder enc) {
super(out);
if (enc == null)
throw new NullPointerException("charset encoder");
se = StreamEncoder.forOutputStreamWriter(out, this, enc);
}java io系列01之 "目录" // 获取编码器enc
public String getEncoding() {
return se.getEncoding();
} // 刷新缓冲区
void flushBuffer() throws IOException {
se.flushBuffer();
} // 将单个字符写入到OutputStreamWriter中
public void write(int c) throws IOException {
se.write(c);
} // 将字符数组cbuf从off开始的数据写入到OutputStreamWriter中,写入长度是len
public void write(char cbuf[], int off, int len) throws IOException {
se.write(cbuf, off, len);
} // 将字符串str从off开始的数据写入到OutputStreamWriter中,写入长度是len
public void write(String str, int off, int len) throws IOException {
se.write(str, off, len);
}java io系列01之 "目录" // 刷新“输出流”
// 它与flushBuffer()的区别是:flushBuffer()只会刷新缓冲,而flush()是刷新流,flush()包括了flushBuffer。
public void flush() throws IOException {
se.flush();
} // 关闭“输出流”
public void close() throws IOException {
se.close();
}
}

说明

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

示例程序

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

 import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.OutputStreamWriter;;
import java.io.InputStreamReader;
import java.io.IOException; /**
* InputStreamReader 和 OutputStreamWriter 测试程序
*
* @author skywang
*/
public class StreamConverter { private static final String FileName = "file.txt";
private static final String CharsetName = "utf-8";
//private static final String CharsetName = "gb2312"; public static void main(String[] args) {
testWrite();
testRead();
} /**
* OutputStreamWriter 演示函数
*
*/
private static void testWrite() {
try {
// 创建文件“file.txt”对应File对象
File file = new File(FileName);
// 创建FileOutputStream对应OutputStreamWriter:将字节流转换为字符流,即写入out1的数据会自动由字节转换为字符。
OutputStreamWriter out1 = new OutputStreamWriter(new FileOutputStream(file), CharsetName);
// 写入10个汉字
out1.write("字节流转为字符流示例");
// 向“文件中”写入"0123456789"+换行符
out1.write("0123456789\n"); out1.close(); } catch(IOException e) {
e.printStackTrace();
}
} /**
* InputStreamReader 演示程序
*/
private static void testRead() {
try {
// 方法1:新建FileInputStream对象
// 新建文件“file.txt”对应File对象
File file = new File(FileName);
InputStreamReader in1 = new InputStreamReader(new FileInputStream(file), CharsetName); // 测试read(),从中读取一个字符
char c1 = (char)in1.read();
System.out.println("c1="+c1); // 测试skip(long byteCount),跳过4个字符
in1.skip(6); // 测试read(char[] cbuf, int off, int len)
char[] buf = new char[10];
in1.read(buf, 0, buf.length);
System.out.println("buf="+(new String(buf))); in1.close();
} catch(IOException e) {
e.printStackTrace();
}
}
}

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

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

java io系列21之 InputStreamReader和OutputStreamWriter的更多相关文章

  1. java io系列01之 "目录"

    java io 系列目录如下: 01. java io系列01之  "目录" 02. java io系列02之 ByteArrayInputStream的简介,源码分析和示例(包括 ...

  2. java io系列

    java io系列01之 "目录" java io系列02之 ByteArrayInputStream的简介,源码分析和示例(包括InputStream) java io系列03之 ...

  3. java io系列22之 FileReader和FileWriter

    FileReader 是用于读取字符流的类,它继承于InputStreamReader.要读取原始字节流,请考虑使用 FileInputStream.FileWriter 是用于写入字符流的类,它继承 ...

  4. java io系列16之 PrintStream(打印输出流)详解

    本章介绍PrintStream以及 它与DataOutputStream的区别.我们先对PrintStream有个大致认识,然后再深入学习它的源码,最后通过示例加深对它的了解. 转载请注明出处:htt ...

  5. Java IO系列之一:IO

    1. 概述 Java IO一般包含两个部分: 1.java.io包中堵塞型IO: 2.java.nio包中的非堵塞型IO,通常称为New IO. java.io包下,分为四大块近80个类: 1.基于字 ...

  6. java io系列25之 PrintWriter (字符打印输出流)

    更多内容请参考:java io系列01之 "目录" PrintWriter 介绍 PrintWriter 是字符类型的打印输出流,它继承于Writer.PrintStream 用于 ...

  7. java io系列06之 序列化总结(Serializable 和 Externalizable)

    本章,我们对序列化进行深入的学习和探讨.学习内容,包括序列化的作用.用途.用法,以及对实现序列化的2种方式Serializable和Externalizable的深入研究. 转载请注明出处:http: ...

  8. java io系列15之 DataOutputStream(数据输出流)的认知、源码和示例

    本章介绍DataOutputStream.我们先对DataOutputStream有个大致认识,然后再深入学习它的源码,最后通过示例加深对它的了解. 转载请注明出处:http://www.cnblog ...

  9. java io系列17之 System.out.println("hello world")原理

    我们初学java的第一个程序是"hello world" public class HelloWorld { public static void main(String[] ar ...

随机推荐

  1. 网络流24(san)题题解汇总

    开坑(烂尾预定 1.餐巾计划问题 题解 2.最小路径覆盖问题 题解 3.试题库问题 题解 4.[CTSC1999]家园 题解 5.骑士共存问题 题解 6.最长不下降子序列问题 题解 7.深海机器人问题 ...

  2. Java归并排序的递归与非递归实现

    该命题已有无数解释,备份修改后的代码 平均时间复杂度: O(NLogN)  以2为底 最好情况时间复杂度: O(NLogN) 最差情况时间复杂度: O(NLogN) 所需要额外空间: 递归:O(N + ...

  3. PHP no input file specified 三种解决方法

    一.IIS Noinput file specified   (IIS上报的错误) 方法一:改PHP.ini中的doc_root行,打开ini文件注释掉此行,然后重启IIS 方法二: 请修改php.i ...

  4. 怎么让 Lua 5.3.4 支持中文变量名和中文函数名

    1. 在官网下载最新版Lua源码 Lua :Download 2. 解压后进入目录,找到/src/llex.c,打开修改 找到如下内容 修改为下面代码,并保存. default: { if (lisl ...

  5. HNOI2017 抛硬币 (FakeBeng)

    除了队长快跑外最难的题吧. 除了需要写\(exLucas\)之外,还教会了我大量的卡常技巧. 首先\(70\)分就是个直接按题意模拟,易得\(ans=\sum_{j=0}^{b} C_{b}^{j}\ ...

  6. SPOJ divcntk(min25筛)

    题意 \(\sigma_0(i)\) 表示 \(i\) 的约数个数 求 \[ S_k(n)=\sum_{i=1}^n\sigma_0(i^k)\pmod {2^{64}} \] 共 \(T\) 组数据 ...

  7. android Button 属性

    Android中button 继承了TextView组件. 可以这么用: final TextView tv = new Button(getApplicationContext()); tv.set ...

  8. 每天一个linux命令(1):wc命令

    Linux系统中的wc(Word Count)命令的功能为统计指定文件中的字节数.字数.行数,并将统计结果显示输出. 1.命令格式: wc [选项]文件... 2.命令功能: 统计指定文件中的字节数. ...

  9. docker-compose.yml(4)

    实例3:version: '3'services: mysql: image: mysql network_mode: "host" environment: - MYSQL_RO ...

  10. [SCOI2010]幸运数字(容斥+爆搜)

    在中国,很多人都把6和8视为是幸运数字!lxhgww也这样认为,于是他定义自己的“幸运号码”是十进制表示中只包含数字6和8的那些号码,比如68,666,888都是“幸运号码”!但是这种“幸运号码”总是 ...