1. 字节流
- 处理音频、视频、文件等,用字节流
1.1 InputStream / OutputStream
- 抽象类
public abstract class InputStream implements Closeable {
// 读取一个字节数据,并返回读到的数据。如果返回 -1,表示读到了输入流的末尾
public abstract int read() throws IOException;
// 将数据读入一个字节数组,同时返回实际读取的字节数。如果返回 -1,表示读到了输入流的末尾
public int read(byte b[]) throws IOException {}
// 将数据读入一个字节数组,同时返回实际读取的字节数。如果返回 -1,表示读到了输入流的末尾。off 指定在数组 b 中存放数据的起始偏移位置;len 指定读取的最大字节数。
public int read(byte b[], int off, int len) throws IOException {}
}
public abstract class OutputStream implements Closeable, Flushable {
// 往输出流中写入一个字节
public abstract void write(int b) throws IOException;
// 往输出流中写入数组b中的所有字节
public void write(byte b[]) throws IOException {}
// 往输出流中写入数组 b 中从偏移量 off 开始的 len 个字节的数据
public void write(byte b[], int off, int len) throws IOException {}
// 强制缓冲区中的输出字节被写出
public void flush() throws IOException {}
// 关闭输出流,释放和这个流相关的系统资源
public void close() throws IOException {}
}
1.2 节点流:直接处理数据
1.2.1 访问文件:File
FileInputStream,FileOutputStrean
1.2.2 访问数组:ByteArray
ByteArrayInputStream,ByteArrayOutputStream
1.2.3 访问管道:Piped
PipedInputStream,PipedOutputStream
1.3 处理流:装饰加工节点流
处理流是对一个已存在的流的连接和封装,通过所封装的流的功能调用实现数据读写。处理流的构造方法总是要带一个其他的流对象做参数。通过关闭处理流里面的节点流来关闭处理流。
1.3.1 Object
- ObjectInputStream:参考链接
反序列化流,将之前使用 ObjectOutputStream 序列化的原始数据恢复为对象,以流的方式读取对象。
- ObjectOutputStream
1.3.2 Filter
- FilterInputStream所有的子类都是为基础流输入提供了一些额外的功能,采用装饰器模式
protected volatile InputStream in;
protected FilterInputStream(InputStream in) {
this.in = in;
}
- 装饰器模式和继承的区别
如果采用继承实现DataInputStream,需要继承多个基础节点流及其子类,耦合性高,类过多;相反,采用装饰器模式,只需要继承FilterInputStream,并动态添加功能扩展,再依据需要传入对应的基础节点流,降低耦合。
1.3.2.1 Buffered
- BufferedInputStrean
- BufferedOutputStream
1.3.2.2 Data
- DataInputStream
- DataOutputStream
1.3.2.3 Pushback:实现回退功能
- PushbackInputStream:参考链接
public class PushbackInputStream extends FilterInputStream {
// 内部维护一个缓冲数组:在数组中从右往左保存回退的数据
protected byte[] buf;
// buf的指针。buf中没数据,pos==buf.length,buf满,pos==0。
protected int pos;
// 读取一个字节
public int read() throws IOException {
ensureOpen(); // 确保流打开
if (pos < buf.length) { // buf中有数据
return buf[pos++] & 0xff; // 把缓冲区中读出来,pos右移
}
return super.read();
}
// 读取多个字节
public int read(byte[] b, int off, int len) throws IOException {
ensureOpen();
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 avail = buf.length - pos; // 缓冲区中有效字节个数
if (avail > 0) { // 优先读缓冲区字节
if (len < avail) {
avail = len;
}
System.arraycopy(buf, pos, b, off, avail);
pos += avail;
off += avail;
len -= avail; // 注意这里
}
if (len > 0) { // 还需要读取字节
len = super.read(b, off, len); // 从InputStream中读取
if (len == -1) {
return avail == 0 ? -1 : avail;
}
return avail + len;
}
return avail;
}
}
1.3.3 Sequence:合并
- SequenceInputStream
1.3.4 StringBuffer
- StringBufferInputStream
2. 字符流
- 处理文本,能使用字符流一定可以使用字节流(字符是由字节组成)
2.1 Reader / Writer
2.2 节点流
2.2.1 访问文件:File
FileReader,FileWriter
2.2.2 访问数组
CharArrayReader,CharArrayWriter
2.2.3 访问管道
PipedInputStream,PipedOutputStream
2.2.4 访问字符串
CharArrayReader,CharArrayWriter
2.3 处理流
2.3.1 缓冲
BufferedReader ,BufferedWriter
2.3.2 转换
InputStreamReader,OutputStreamWriter