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 ...
随机推荐
- JVM方法调用过程
JVM方法调用过程 重载和重写 同一个类中,如果出现多个名称相同,并且参数类型相同的方法,将无法通过编译.因此,想要在同一个类中定义名字相同的方法,那么它们的参数类型必须不同.这种方法上的联系就是重载 ...
- Luogu5245 【模板】多项式快速幂(多项式exp)
A(x)k=eklnA(x).泰勒展开之后容易发现k并非在指数上,所以对p取模. #include<iostream> #include<cstdio> #include< ...
- Codeforces Round #545 Div. 1自闭记
A:求出该行该列各有多少个比其小的取max,该行该列各有多少个比其大的取max,加起来即可. #include<iostream> #include<cstdio> #incl ...
- eolinker——分享项目只需两步
登陆后打开项目概况 然后进入到分享项目界面,可根据自己的需求进行设置
- P1387 最大正方形 dp
思路: i j的最大正方形等于min(他的斜上方的的最大正方形,他的上方有的连续1,他的左方有的连续1)+1 #include<bits/stdc++.h> using namespac ...
- scrapy入门与进阶
Scrapy是用纯Python实现一个为了爬取网站数据.提取结构性数据而编写的应用框架,用途非常广泛. 框架的力量,用户只需要定制开发几个模块就可以轻松的实现一个爬虫,用来抓取网页内容以及各种图片,非 ...
- 【XSY2665】没有上司的舞会 LCT DP
题目大意 有一棵树,最开始只有一个点.每次会往这棵树中加一个点,总共\(n\)次.输出每次加点后树的最大独立集大小. 强制在线. \(n\leq 300000\) 题解 显然是LCT. 那么要维护什么 ...
- SCOI 2015 Day2 简要题解
「SCOI2015」小凸玩密室 题意 小凸和小方相约玩密室逃脱,这个密室是一棵有 $ n $ 个节点的完全二叉树,每个节点有一个灯泡.点亮所有灯泡即可逃出密室.每个灯泡有个权值 $ A_i $,每条边 ...
- 牛客网Wannafly挑战赛25A 因子(数论 素因子分解)
链接:https://www.nowcoder.com/acm/contest/197/A来源:牛客网 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 262144K,其他语言5242 ...
- 区块链使用Java,以太坊 Ethereum, web3j, Spring Boot
Blockchain is one of the buzzwords in IT world during some last months. This term is related to cryp ...