package java.io;
public class BufferedOutputStream extends FilterOutputStream {
//存储数据的内部缓冲区,存储"缓冲输入流"数据的字节数组
protected byte buf[];
//缓冲区中的有效字节数,即缓冲区数据的个数
protected int count;
//构造器:创建了一个新的缓存区为默认字节为8192大小的“缓冲输出流”
public BufferedOutputStream(OutputStream out) {
this(out, 8192);
}
//创建一个新的缓冲输出流,大小为size
public BufferedOutputStream(OutputStream out, int size) {
super(out);
if (size <= 0) { //size<=0会报非法参数异常
throw new IllegalArgumentException("Buffer size <= 0");
}
buf = new byte[size];
}
//冲刷缓存区
private void flushBuffer() throws IOException {
if (count > 0) {
out.write(buf, 0, count);
count = 0;
}
}
//将指定的字节写到这个缓冲的输出流
public synchronized void write(int b) throws IOException {
// 若缓冲已满,则先将缓冲数据写入到输出流中。
if (count >= buf.length) {
flushBuffer();
}
// 将“数据b”写入到缓冲中
buf[count++] = (byte)b;
}
//
public synchronized void write(byte b[], int off, int len) throws IOException {
// 若"写入长度len"大于"缓冲区大小",会先进行冲刷,将缓冲中的数据写入到输出流,
// 然后直接将数组b写入到输出流中
if (len >= buf.length) {
flushBuffer();
out.write(b, off, len);
return;
}
//若"写入的长度len"大于"缓冲区剩余的空间",会先将缓冲区进行冲刷,然后将b[]写入缓冲区
if (len > buf.length - count) {
flushBuffer();
}
System.arraycopy(b, off, buf, count, len);
count += len;
}
//冲刷,调用flushBuffer()方法,将“缓冲数据”写入到输出流中,
//flush()方法可以强迫输出流(或缓冲的流)发送数据,即使此时缓冲区还没有填满,以此来打破这种死
//锁的状态。
public synchronized void flush() throws IOException {
flushBuffer();
out.flush();
}
}
flush():作用是冲刷缓冲区中的数据,这个作用尤为重要。
例如,缓冲区大小为8192,然后你传入了一个比缓冲区小的文件,这时候因为缓冲区没有满,它不进行自动刷新。
所以我们不进行flush()冲刷的话会造成文件的数据丢失。
所以我们在输出流是BufferOutputStream时,在完成write()后添加flush();
当然如果将流关闭,即使用close()时,可以不进行flush(),因为close()底层源码中有flush()方法;
write(byte b[], int off, int len)
如果写入的len大于定义的缓冲区大小,会直接写到输出流中,不经过缓冲区。
如果写入的len不大于缓冲区,但是大于缓冲区剩余空间的大小,会先将缓冲区的数据写入输出流中,在将b[]写入缓冲区