声明:本系列只供本人自学使用,勿喷。
IO是每位java工程师都必须掌握的知识点,无论什么项目都会涉及文件IO、网络IO等,但是java中的IO类多达几十种,很多人在使用时会难以抉择,并且网上关于IO的学习资料比较杂乱,因此本人决定研究JDK8中rt.jar的java.io源码并总结为系列文章,如有不正之处还请多多指点。
网上的IO教程大多是一上来就扔个降视力的大图,吓得我等小白直接X掉网页。本人痛定思痛,决定从0扩展IO体系,首先我们按照操作单元进行划分,如下图。
程序中的所有数据都是以流的方式存储或传输,通常情况下,二进制数据(Binary)使用字节流传输、存储,文本数据(ASCII)使用字符流传输、存储、读取。
一、字节流
1.InputStream
- 源码结构图
- 核心方法
核心方法就是read,读取InputStream并保存到byte[]
// 返回下一个字节,如果没有则返回-1
public abstract int read() throws IOException
// 实际调用read(b, 0, b.length);
public int read(byte b[]) throws IOException
public int read(byte b[], int off, int len) throws IOException{
1.参数检查
2.循环read(),赋值给b
3.返回上一步赋值给b的字节数量
}
public void close() throws IOException
- 其余方法
// 跳过n个字节
public long skip(long n) throws IOException{
1. size=(常量MAX_SKIP_BUFFER_SIZE与入参n的较小值)
2. 循环read()赋值给临时数组new byte[size]
}
// 返回InputStream的字节数,但是并不准确
public int available() throws IOException
// 标记,回到标记位,是否支持该功能
public synchronized void mark(int readlimit)
public synchronized void reset() throws IOException
public boolean markSupported()
2.OutputStream
- 源码结构图
- 核心方法
核心方法就是write,将byte[]写入OutputStream
public abstract void write(int b) throws IOException;
// 实际调用write(b, 0, b.length);
public void write(byte b[]) throws IOException
public void write(byte b[], int off, int len) throws IOException{
1.参数检查
2.循环write()
}
// 保证字节数组传递给底层操作系统,不能保证操作系统已完成写入
public void flush() throws IOException
public void close() throws IOException
二、字符流
1.Reader
-
源码结构图
- 构造器
// 用来实现同步操作,子类如果需要同步,也应使用synchronized (lock)
protected Object lock;
protected Reader() {
this.lock = this;
}
protected Reader(Object lock) {
if (lock == null) {
throw new NullPointerException();
}
this.lock = lock;
}
- 核心方法
核心方法就是read,读取Reader并保存到char[]
// 返回下一个字符,如果没有则返回-1
public int read() throws IOException
// 实际调用read(cbuf, 0, cbuf.length);
public int read(char cbuf[]) throws IOException
abstract public int read(char cbuf[], int off, int len) throws IOException
//JDK5新增
public int read(java.nio.CharBuffer target) throws IOException{
1.读取target.remaining()个字符到char[]
2.将char[]赋值给target
}
public void close() throws IOException
- 其余方法
// 跳过n个字节
public long skip(long n) throws IOException{
1. size=(常量maxSkipBufferSize与入参n的较小值)
2. 循环read()赋值给临时数组new byte[size]
}
// 下一次read()是否阻塞
public boolean ready() throws IOException
// 标记,回到标记位,是否支持该功能
public synchronized void mark(int readlimit)
public synchronized void reset() throws IOException
public boolean markSupported()
2.Writer
-
源码结构图
- 构造器(同Reader)
// 用来实现同步操作,子类如果需要同步,也应使用synchronized (lock)
protected Object lock;
protected Writer() {
this.lock = this;
}
protected Writer(Object lock) {
if (lock == null) {
throw new NullPointerException();
}
this.lock = lock;
}
- 核心方法
核心方法
① write,将char[] 写入Writer
② append,将CharSequence追加到Writer
// 以下方法实际调用write(char cbuf[], int off, int len)
public void write(int c) throws IOException
public void write(char cbuf[]) throws IOException
public void write(String str) throws IOException
public void write(String str, int off, int len) throws IOException
//JDK5新增
public Writer append(CharSequence csq) throws IOException
public Writer append(CharSequence csq, int start, int end) throws IOException
public Writer append(char c) throws IOException
abstract public void write(char cbuf[], int off, int len) throws IOException;
// 保证字符数组传递给底层操作系统,不能保证操作系统已完成写入
public void flush() throws IOException
public void close() throws IOException
三、总结
- 字节流通过字节数组byte[]进行读写操作,InputStream核心方法是read(byte b[], int off, int len),OutputStream核心方法是write(byte b[], int off, int len)
- 字符流通过字符数组char[]进行读写操作,Reader核心方法是read(char cbuf[], int off, int len),Writer核心方法是write(char cbuf[], int off, int len)
- 无论读取哪种流,read返回值为-1表示结束,其他值则表示已读取到数组中的数量。
本节讨论的类都是抽象类,力求从宏观上了解这些类各自的作用,接下来的系列将深入具体的实现类源码,并用简单demo示例进行说明。由于输入流、输出流代码相似,并且在使用时一般都成对出现,下文也将成对讲解。
网友评论