java io系列21之 InputStreamReader和OutputStreamWriter
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的更多相关文章
- java io系列01之 "目录"
java io 系列目录如下: 01. java io系列01之 "目录" 02. java io系列02之 ByteArrayInputStream的简介,源码分析和示例(包括 ...
- java io系列
java io系列01之 "目录" java io系列02之 ByteArrayInputStream的简介,源码分析和示例(包括InputStream) java io系列03之 ...
- java io系列22之 FileReader和FileWriter
FileReader 是用于读取字符流的类,它继承于InputStreamReader.要读取原始字节流,请考虑使用 FileInputStream.FileWriter 是用于写入字符流的类,它继承 ...
- java io系列16之 PrintStream(打印输出流)详解
本章介绍PrintStream以及 它与DataOutputStream的区别.我们先对PrintStream有个大致认识,然后再深入学习它的源码,最后通过示例加深对它的了解. 转载请注明出处:htt ...
- Java IO系列之一:IO
1. 概述 Java IO一般包含两个部分: 1.java.io包中堵塞型IO: 2.java.nio包中的非堵塞型IO,通常称为New IO. java.io包下,分为四大块近80个类: 1.基于字 ...
- java io系列25之 PrintWriter (字符打印输出流)
更多内容请参考:java io系列01之 "目录" PrintWriter 介绍 PrintWriter 是字符类型的打印输出流,它继承于Writer.PrintStream 用于 ...
- java io系列06之 序列化总结(Serializable 和 Externalizable)
本章,我们对序列化进行深入的学习和探讨.学习内容,包括序列化的作用.用途.用法,以及对实现序列化的2种方式Serializable和Externalizable的深入研究. 转载请注明出处:http: ...
- java io系列15之 DataOutputStream(数据输出流)的认知、源码和示例
本章介绍DataOutputStream.我们先对DataOutputStream有个大致认识,然后再深入学习它的源码,最后通过示例加深对它的了解. 转载请注明出处:http://www.cnblog ...
- java io系列17之 System.out.println("hello world")原理
我们初学java的第一个程序是"hello world" public class HelloWorld { public static void main(String[] ar ...
随机推荐
- windows电脑连接蓝牙耳机的正确步骤
前言 我使用的是小米运动蓝牙耳机,操作系统为win7,废话少说直接上教程 是否支持蓝牙功能 按住win+R,打开[运行],输入devmgmt.msc,回车. 只要有Bluetooth 无线电收发器,那 ...
- Codeforces 768B B. Code For 1
参考自:https://www.cnblogs.com/ECJTUACM-873284962/p/6423483.html B. Code For 1 time limit per test:2 se ...
- hdu 2159 FATE (二维完全背包)
链接:http://acm.hdu.edu.cn/showproblem.php?pid=2159 思路: dp[j][k] 代表消耗耐久度j,干掉k个敌人获得的经验值. 状态转移方程为: dp[j] ...
- 【hdu6188】Duizi and Shunzi(贪心)
2017ACM/ICPC广西邀请赛 重现赛1007 Duizi and Shunzi 题意 有n张牌,问你最多能组成多少对子+顺子?一个牌只能用在一个顺子或者对子中. 题解 本来想写dp的,不会..小 ...
- SCOI 2015 Day1 简要题解
「SCOI2015」小凸玩矩阵 题意 一个 \(N \times M\)( $ N \leq M $ )的矩阵 $ A $,要求小凸从其中选出 $ N $ 个数,其中任意两个数字不能在同一行或同一列, ...
- Hdoj 1374.Knight Moves 题解
Problem Description A friend of you is doing research on the Traveling Knight Problem (TKP) where yo ...
- android TextView字体设置最少占多少行. 及其 Java String 字符串操作 . .
① 字体设置: 修改代码 : GridViewActivity.java priceTv为 TextView priceTv.setMaxLines(3); //当多与7个字fu的时候 , 其余字 ...
- js-基本语法2
类型转换 1.直接转换 parseInt() 与 parseFloat() alert('12'+7); //弹出127 alert( parseInt('12') + 7 ); //弹出19 ale ...
- 「JLOI2015」战争调度 解题报告
「JLOI2015」战争调度 感觉一到晚上大脑就宕机了... 题目本身不难,就算没接触过想想也是可以想到的 这个满二叉树的深度很浅啊,每个点只会和它的\(n-1\)个祖先匹配啊 于是可以暴力枚举祖先链 ...
- 录毛线脚本,直接抓包手写最简洁的LoadRunner性能测试脚本
通常情况下,我们测试性能先要做单场景测试,即某个功能,一般情况下,这个功能依赖的功能(可能是需要先登录)不会太多, 如果录制脚本的话,会录制到很多无关的请求,大大增加了脚本的复杂度以及调整脚本的工作量 ...