1 InputStream 子类结构
- 下图是 InputStream 及其子类的结构图。可以看出 InputStream 是一个典型的装饰者模式的示例
- InputStream:抽象的组件类,具体的组件类继承它,来实现不同的输入流功能
- FilterInputStream:抽象装饰者类,具体装饰者类继承它,来对它包装的组件类,进行扩展
- Java IO 的扩展:
- 添加具体组件类,实现特定的输入流功能
- 添加具体装饰类,达到保证组件类的目的
![在这里插入图片描述](https://img-blog.csdnimg.cn/20191030225312296.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2thbmdzYTk5OA==,size_16,color_FFFFFF,t_70)
1.1 InputStream 源码分析
- inputStream抽象类功能
- 定义读取一个字节 或 多个字节的 方法
- 定义了 mark、reset 的方法,由具体子类实现 重复读取一段数据流的功能
- 定义了关闭输入流的方法
- 定义了返回剩余可读取字节的方法
- 注: 只有读取一个字节的 read() 方法是抽象的,也就是说,具体类只要实现这一个方法即可,其它的可不实现
public abstract class InputStream implements Closeable {
public abstract int read() throws IOException;
public int read(byte b[]) throws IOException {
return read(b, 0, b.length);
}
public int read(byte b[], int off, int len) throws IOException {
...}
public long skip(long n) throws IOException {
...}
public int available() throws IOException {
return 0;
}
public void close() throws IOException {
}
public synchronized void mark(int readlimit) {
}
public synchronized void reset() throws IOException {
throw new IOException("mark/reset not supported");
}
public boolean markSupported() {
return false;
}
private static final int MAX_SKIP_BUFFER_SIZE = 2048;
}
2 InputStream 具体实现类源码分析
2.1 ByteArrayInputStream —— 字节输入流
- 核心: buf[] 数组,这个数组即是数据流的 源
- 字节流操作即是,操作数组的位置 pos。思想很简单
- 基本所有操作都被 synchronized 修饰
public class ByteArrayInputStream extends InputStream {
protected byte buf[];
protected int pos;
protected int mark = 0;
protected int count;
public synchronized int read() {
return (pos < count) ? (buf[pos++] & 0xff) : -1;
}
public synchronized int read(byte b[], int off, int len) {
...}
public synchronized long skip(long n) {
}
public synchronized int available() {
}
public void mark(int readAheadLimit) {
mark = pos;
}
public synchronized void reset() {
pos = mark;
}
public void close() throws IOException {
}
public ByteArrayInputStream(byte buf[]) {
this.buf = buf;
this.pos = 0;
this.count = buf.length;
}
public ByteArrayInputStream(byte buf[], int offset, int length) {
this.buf = buf;
this.pos = offset;
this.count = Math.min(offset + length, buf.length);
this.mark = offset;
}
}
2.2 FileInputStream —— 文件输入流
- 核心: file、fileDescriptor
- 通过构造函数 传入 fileName 或 File 类,内部创建一个 文件链接
- 核心功能实现方法(本地方法):
- read0():获取下一个字节
- readBytes(byte b[], int off, int len):从偏移量 off 开始,读取 len 个字节,放入 b[] 数组中
- skip0(long n):跳过 n 个字节
- available0():还剩多少字节
- close0():关闭文件流
- 方法没有被 synchronized 修饰,因为最终调用的是本地方法,本地方法应该加了手段
public class FileInputStream extends InputStream {
private final FileDescriptor fd;
private final String path;
private FileChannel channel = null;
private final Object closeLock = new Object();
private volatile boolean closed = false;
public