实现思路
- 继承抽象装饰者类:Java I/O中的
FilterInputStream
(用于字节流)或FilterReader
(用于字符流)是抽象装饰者类,自定义缓冲流需继承其中之一。
- 组合基础流:在自定义类的构造函数中,接受一个基础的输入流对象,以便在装饰者模式中对其进行功能增强。
- 实现缓冲机制:定义一个缓冲区数组,重写
read
方法来实现从缓冲区读取数据,当缓冲区数据读完后,再从基础流中填充缓冲区。
关键代码片段(以字节流为例,继承FilterInputStream
)
import java.io.FilterInputStream;
import java.io.IOException;
import java.io.InputStream;
public class MyBufferedInputStream extends FilterInputStream {
private static final int DEFAULT_BUFFER_SIZE = 8192;
private byte[] buffer;
private int count;
private int pos;
public MyBufferedInputStream(InputStream in) {
this(in, DEFAULT_BUFFER_SIZE);
}
public MyBufferedInputStream(InputStream in, int size) {
super(in);
if (size <= 0) {
throw new IllegalArgumentException("Buffer size <= 0");
}
buffer = new byte[size];
}
@Override
public int read() throws IOException {
if (pos >= count) {
fillBuffer();
if (pos >= count) {
return -1;
}
}
return buffer[pos++] & 0xff;
}
@Override
public int read(byte[] b, int off, int len) throws IOException {
if (len == 0) {
return 0;
}
int avail = count - pos;
if (avail <= 0) {
if ((count = fillBuffer()) <= 0) {
return -1;
}
avail = count - pos;
}
int cnt = (avail < len)? avail : len;
System.arraycopy(buffer, pos, b, off, cnt);
pos += cnt;
return cnt;
}
private int fillBuffer() throws IOException {
pos = 0;
return in.read(buffer);
}
}
关键方法重写说明
read()
方法:首先检查缓冲区是否还有数据,如果没有则调用fillBuffer()
方法填充缓冲区,然后从缓冲区返回一个字节数据。
read(byte[] b, int off, int len)
方法:计算缓冲区中可用的数据量,如果不够则填充缓冲区,然后将缓冲区中的数据复制到目标数组b
中,返回实际读取的字节数。
fillBuffer()
方法:从基础输入流in
中读取数据填充到缓冲区,并返回读取的字节数。如果读取到流末尾则返回 -1。