有了装饰者模式,就可以继续了解java的IO类,
InputStream 抽象组件
FileInputStream,StringBufferInputStream,ByteArrayInputStream等是具体组件
FilterInputStream是一个抽象的装饰者
PushbackInputStream,BufferInputStream,DataInputStream,LineNumberInputStream这些是具体装饰者
可以发现,java中的IO类型就是使用了装饰者模式。
在java1.6中关于和IO类的定义有
类 | 功能 |
---|---|
BufferedInputStream | 为另一个输入流添加一些功能,即缓冲输入以及支持 mark 和 reset 方法的能力。 |
BufferedOutputStream | 该类实现缓冲的输出流。 |
BufferedReader | 从字符输入流中读取文本,缓冲各个字符,从而实现字符、数组和行的高效读取。 |
BufferedWriter | 将文本写入字符输出流,缓冲各个字符,从而提供单个字符、数组和字符串的高效写入。 |
ByteArrayInputStream ByteArrayInputStream | 包含一个内部缓冲区,该缓冲区包含从流中读取的字节。 |
ByteArrayOutputStream | 此类实现了一个输出流,其中的数据被写入一个 byte 数组。 |
CharArrayReader | 此类实现一个可用作字符输入流的字符缓冲区。 |
CharArrayWriter | 此类实现一个可用作 Writer 的字符缓冲区。 |
Console | 此类包含多个方法,可访问与当前 Java 虚拟机关联的基于字符的控制台设备(如果有)。 |
DataInputStream | 数据输入流允许应用程序以与机器无关方式从底层输入流中读取基本 Java 数据类型。 |
DataOutputStream | 数据输出流允许应用程序以适当方式将基本 Java 数据类型写入输出流中。 |
File | 文件和目录路径名的抽象表示形式。 |
FileDescriptor | 文件描述符类的实例用作与基础机器有关的某种结构的不透明句柄,该结构表示开放文件、开放套接字或者字节的另一个源或接收者。 |
FileInputStream | 从文件系统中的某个文件中获得输入字节。 |
FileOutputStream | 文件输出流是用于将数据写入 File 或 FileDescriptor 的输出流。 |
FilePermission | 此类表示对文件和目录的访问。 |
FileReader | 用来读取字符文件的便捷类。 |
FileWriter | 用来写入字符文件的便捷类。 |
FilterInputStream FilterInputStream | 包含其他一些输入流,它将这些流用作其基本数据源,它可以直接传输数据或提供一些额外的功能。 |
FilterOutputStream | 此类是过滤输出流的所有类的超类。 |
FilterReader | 用于读取已过滤的字符流的抽象类。 |
FilterWriter | 用于写入已过滤的字符流的抽象类。 |
InputStream | 此抽象类是表示字节输入流的所有类的超类。 |
InputStreamReader | 是字节流通向字符流的桥梁:它使用指定的 charset 读取字节并将其解码为字符。 |
LineNumberInputStream | 已过时。 此类错误假定字节能充分表示字符。 |
LineNumberReader | 跟踪行号的缓冲字符输入流。 |
ObjectInputStream | 对以前使用 ObjectOutputStream 写入的基本数据和对象进行反序列化。 |
ObjectInputStream.GetField | 提供对从输入流读取的持久字段的访问权限。 |
ObjectOutputStream | 将 Java 对象的基本数据类型和图形写入 OutputStream。 |
ObjectOutputStream.PutField | 提供对要写入 ObjectOutput 的持久字段的编程访问。 |
ObjectStreamClass | 类的序列化描述符。 |
ObjectStreamField Serializable | 类中 Serializable 字段的描述。 |
OutputStream | 此抽象类是表示输出字节流的所有类的超类。 |
OutputStreamWriter | 是字符流通向字节流的桥梁:可使用指定的 charset 将要写入流中的字符编码成字节。 |
PipedInputStream | 管道输入流应该连接到管道输出流;管道输入流提供要写入管道输出流的所有数据字节。 |
PipedOutputStream | 可以将管道输出流连接到管道输入流来创建通信管道。 |
PipedReader | 传送的字符输入流。 |
PipedWriter | 传送的字符输出流。 |
PrintStream | 为其他输出流添加了功能,使它们能够方便地打印各种数据值表示形式。 |
PrintWriter | 向文本输出流打印对象的格式化表示形式。 |
PushbackInputStream | 为另一个输入流添加性能,即“推回 (push back)”或“取消读取 (unread)”一个字节的能力。 |
PushbackReader | 允许将字符推回到流的字符流 reader。 |
RandomAccessFile | 此类的实例支持对随机访问文件的读取和写入。 |
Reader | 用于读取字符流的抽象类。 |
SequenceInputStream | 表示其他输入流的逻辑串联。 |
SerializablePermission | 此类用于可序列化权限。 |
StreamTokenizer | 类获取输入流并将其解析为“标记”,允许一次读取一个标记。 |
StringBufferInputStream | 已过时。 此类未能正确地将字符转换为字节。 |
StringReader | 其源为一个字符串的字符流。 |
StringWriter | 一个字符流,可以用其回收在字符串缓冲区中的输出来构造字符串。 |
Writer | 写入字符流的抽象类。 |
在IO包里的SequenceInputStream 中
package java.io;
import java.io.InputStream;
import java.util.Enumeration;
import java.util.Vector;
public class SequenceInputStream extends InputStream {
Enumeration<? extends InputStream> e;
InputStream in;
public SequenceInputStream(Enumeration<? extends InputStream> e) {
this.e = e;
try {
nextStream();
} catch (IOException ex) {
// This should never happen
throw new Error("panic");
}
}
public SequenceInputStream(InputStream s1, InputStream s2) {
Vector<InputStream> v = new Vector<>(2);
v.addElement(s1);
v.addElement(s2);
e = v.elements();
try {
nextStream();
} catch (IOException ex) {
// This should never happen
throw new Error("panic");
}
}
final void nextStream() throws IOException {
if (in != null) {
in.close();
}
if (e.hasMoreElements()) {
in = (InputStream) e.nextElement();
if (in == null)
throw new NullPointerException();
}
else in = null;
}
public int available() throws IOException {
if (in == null) {
return 0; // no way to signal EOF from available()
}
return in.available();
}
public int read() throws IOException {
while (in != null) {
int c = in.read();
if (c != -1) {
return c;
}
nextStream();
}
return -1;
}
public int read(byte b[], int off, int len) throws IOException {
if (in == null) {
return -1;
} else if (b == null) {
throw new NullPointerException();
} else if (off < 0 || len < 0 || len > b.length - off) {
throw new IndexOutOfBoundsException();
} else if (len == 0) {
return 0;
}
do {
int n = in.read(b, off, len);
if (n > 0) {
return n;
}
nextStream();
} while (in != null);
return -1;
}
public void close() throws IOException {
do {
nextStream();
} while (in != null);
}
}
这是一个直接继承自InputStream类的装饰器,可以同时处理多个InputStream的子类对象。
这种流在java中被称为是处理流(也可以被其他的InputStream类的对象处理)。只能被处理的Input 的对象不能处理其他的InputStream。
java的流一共有多少种:
1:输入流和输出流
按照流的方向流向程序的流(数据汇是程序)被称为输入流,反之(数据源是程序)是输出流
2:字符流和字节流
按照流的处理单位:以字节为单位处理的流是字节流,以字为单位的流是字符流
3:节点流和处理流
按照处理方式:是直接处理数据还是处理已经和数据连接的流,直接处理数据则是节点流,处理别的流则是处理流。
流 | 字节流(1byte) | 字符流(2byte) |
---|---|---|
输入流 | InputStream | Reader |
输出流 | OutputStream | Writer |
IO图解:
输入流:
红色的是节点流而黑色的是处理流。
看看节点流的代码:
StringBufferInputStream是一个具体的组件。它覆盖了InputStream类的一些方法,如read();
代码如下。
package java.io;
@Deprecated
public class StringBufferInputStream extends InputStream {
protected String buffer;
protected int pos;
protected int count;
public StringBufferInputStream(String s) {
this.buffer = s;
count = s.length();
}
public synchronized int read() {
return (pos < count) ? (buffer.charAt(pos++) & 0xFF) : -1;
}
public synchronized int read(byte b[], int off, int len) {
if (b == null) {
throw new NullPointerException();
} else if ((off < 0) || (off > b.length) || (len < 0) ||
((off + len) > b.length) || ((off + len) < 0)) {
throw new IndexOutOfBoundsException();
}
if (pos >= count) {
return -1;
}
if (pos + len > count) {
len = count - pos;
}
if (len <= 0) {
return 0;
}
String s = buffer;
int cnt = len;
while (--cnt >= 0) {
b[off++] = (byte)s.charAt(pos++);
}
return len;
}
public synchronized long skip(long n) {
if (n < 0) {
return 0;
}
if (n > count - pos) {
n = count - pos;
}
pos += n;
return n;
}
public synchronized int available() {
return count - pos;
}
public synchronized void reset() {
pos = 0;
}
}
InputStream 抽象组件为
package java.io;
public abstract class InputStream implements Closeable {
private static final int MAX_SKIP_BUFFER_SIZE = 2048;
public int read(byte b[]) throws IOException {
return read(b, 0, b.length);
}
public int read(byte b[], int off, int len) throws IOException {
if (b == null) {
throw new NullPointerException();
} else if (off < 0 || len < 0 || len > b.length - off) {
throw new IndexOutOfBoundsException();
} else if (len == 0) {
return 0;
}
int c = read();
if (c == -1) {
return -1;
}
b[off] = (byte)c;
int i = 1;
try {
for (; i < len ; i++) {
c = read();
if (c == -1) {
break;
}
b[off + i] = (byte)c;
}
} catch (IOException ee) {
}
return i;
}
public long skip(long n) throws IOException {
long remaining = n;
int nr;
if (n <= 0) {
return 0;
}
int size = (int)Math.min(MAX_SKIP_BUFFER_SIZE, remaining);
byte[] skipBuffer = new byte[size];
while (remaining > 0) {
nr = read(skipBuffer, 0, (int)Math.min(size, remaining));
if (nr < 0) {
break;
}
remaining -= nr;
}
return n - remaining;
}
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;
}
}
本文参考了:
http://www.cnblogs.com/shitouer/archive/2012/12/19/2823641.html
还有《Head First设计模式》