本文记录BufferedInputStream,BufferedOutputStream两个带缓冲的输入输出流。

BufferedInputStream继承于FilterInputStream,BufferedOutputStream继承于FilterOutputStream,这两个类为具体的装饰类,而FilterInputStream与FilterOutputStream为抽象装饰者类,但是该两个类不是抽象类。

BufferedInputStream

下面是BufferedInputStream的源码:

public class BufferedInputStream extends FilterInputStream {//默认缓冲区大小private static int DEFAULT_BUFFER_SIZE = 8192;//最大缓冲区大小private static int MAX_BUFFER_SIZE = Integer.MAX_VALUE - 8;//内部缓冲数组protected volatile byte buf[];//为buf缓冲区提供原子的更新器private static finalAtomicReferenceFieldUpdater<BufferedInputStream, byte[]> bufUpdater =AtomicReferenceFieldUpdater.newUpdater(BufferedInputStream.class,  byte[].class, "buf");//该值表示缓冲区下一个接收Input Stream字节的位置protected int count;//缓冲区的当前位置,也就是下一个从缓冲区读数据的位置,该值小于等于countprotected int pos;//Mark标记的位置protected int markpos = -1;//pos - markpos > marklimit 时,Mark标记清除protected int marklimit;//获取该对象相应的InputStream对象private InputStream getInIfOpen() throws IOException {InputStream input = in;if (input == null)throw new IOException("Stream closed");return input;}//获取buf缓冲区private byte[] getBufIfOpen() throws IOException {byte[] buffer = buf;if (buffer == null)throw new IOException("Stream closed");return buffer;}//构造方法,调用父类方法,用于对InputStream 对象进行增强public BufferedInputStream(InputStream in) {this(in, DEFAULT_BUFFER_SIZE);}public BufferedInputStream(InputStream in, int size) {super(in);if (size <= 0) {throw new IllegalArgumentException("Buffer size <= 0");}buf = new byte[size];}//读入字节填充缓冲区private void fill() throws IOException {byte[] buffer = getBufIfOpen();//如果标记位无效,则直接填充缓冲区,并且覆盖原来的字节if (markpos < 0)pos = 0;            /* no mark: throw away the buffer */else if (pos >= buffer.length)  /* no room left in buffer */if (markpos > 0) {  /* can throw away early part of the buffer */int sz = pos - markpos;System.arraycopy(buffer, markpos, buffer, 0, sz);pos = sz;markpos = 0;} else if (buffer.length >= marklimit) {markpos = -1;   /* buffer got too big, invalidate mark */pos = 0;        /* drop buffer contents */} else if (buffer.length >= MAX_BUFFER_SIZE) {throw new OutOfMemoryError("Required array size too large");} else {            /* grow buffer */int nsz = (pos <= MAX_BUFFER_SIZE - pos) ?pos * 2 : MAX_BUFFER_SIZE;if (nsz > marklimit)nsz = marklimit;byte nbuf[] = new byte[nsz];System.arraycopy(buffer, 0, nbuf, 0, pos);if (!bufUpdater.compareAndSet(this, buffer, nbuf)) {// Can't replace buf if there was an async close.// Note: This would need to be changed if fill()// is ever made accessible to multiple threads.// But for now, the only way CAS can fail is via close.// assert buf == null;throw new IOException("Stream closed");}buffer = nbuf;}count = pos;int n = getInIfOpen().read(buffer, pos, buffer.length - pos);if (n > 0)count = n + pos;}//向缓冲区读取一个数据,若缓冲区没有数据,则使用fill方法填充缓冲区public synchronized int read() throws IOException {if (pos >= count) {fill();if (pos >= count)return -1;}return getBufIfOpen()[pos++] & 0xff;}//读取字节至相应数组(private方法)private int read1(byte[] b, int off, int len) throws IOException {int avail = count - pos;if (avail <= 0) {/* If the requested length is at least as large as the buffer, andif there is no mark/reset activity, do not bother to copy thebytes into the local buffer.  In this way buffered streams willcascade harmlessly. */if (len >= getBufIfOpen().length && markpos < 0) {return getInIfOpen().read(b, off, len);}fill();avail = count - pos;if (avail <= 0) return -1;}int cnt = (avail < len) ? avail : len;System.arraycopy(getBufIfOpen(), pos, b, off, cnt);pos += cnt;return cnt;}//读取相应字节至数组,为一个同步方法,线程安全public synchronized int read(byte b[], int off, int len)throws IOException{getBufIfOpen(); // Check for closed streamif ((off | len | (off + len) | (b.length - (off + len))) < 0) {throw new IndexOutOfBoundsException();} else if (len == 0) {return 0;}int n = 0;for (;;) {int nread = read1(b, off + n, len - n);if (nread <= 0)return (n == 0) ? nread : n;n += nread;if (n >= len)return n;// if not closed but no bytes available, returnInputStream input = in;if (input != null && input.available() <= 0)return n;}}//跳过n个字节public synchronized long skip(long n) throws IOException {getBufIfOpen(); // Check for closed streamif (n <= 0) {return 0;}long avail = count - pos;if (avail <= 0) {// If no mark position set then don't keep in bufferif (markpos <0)return getInIfOpen().skip(n);// Fill in buffer to save bytes for resetfill();avail = count - pos;if (avail <= 0)return 0;}long skipped = (avail < n) ? avail : n;pos += skipped;return skipped;}public synchronized int available() throws IOException {int n = count - pos;int avail = getInIfOpen().available();return n > (Integer.MAX_VALUE - avail)? Integer.MAX_VALUE: n + avail;}public synchronized void mark(int readlimit) {marklimit = readlimit;markpos = pos;}public synchronized void reset() throws IOException {getBufIfOpen(); // Cause exception if closedif (markpos < 0)throw new IOException("Resetting to invalid mark");pos = markpos;}public boolean markSupported() {return true;}public void close() throws IOException {byte[] buffer;while ( (buffer = buf) != null) {if (bufUpdater.compareAndSet(this, buffer, null)) {InputStream input = in;in = null;if (input != null)input.close();return;}// Else retry in case a new buf was CASed in fill()}}
}

BufferedOutputStream

public
class BufferedOutputStream extends FilterOutputStream {//buffer数组protected byte buf[];//buffer中有效值protected int count;public BufferedOutputStream(OutputStream out) {this(out, 8192);}public BufferedOutputStream(OutputStream out, int size) {super(out);if (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();}buf[count++] = (byte)b;}//写入一个字节数组public synchronized void write(byte b[], int off, int len) throws IOException {//如果需要写入的长度大于缓冲区大小,则先清空缓冲区(将缓冲区所有字节写出),再写出该字节。if (len >= buf.length) {/* If the request length exceeds the size of the output buffer,flush the output buffer and then write the data directly.In this way buffered streams will cascade harmlessly. */flushBuffer();out.write(b, off, len);return;}//如果剩下的缓冲区容量放不下需要写入的字节长度,则把缓冲区字节写出if (len > buf.length - count) {flushBuffer();}//将相应字节数组复制至缓冲区System.arraycopy(b, off, buf, count, len);count += len;}//强制刷新缓冲,将缓冲内的数据写出至Output Streampublic synchronized void flush() throws IOException {flushBuffer();out.flush();}
}

Java IO流源码学习之二(Buffered字节流)相关推荐

  1. 第三课 k8s源码学习和二次开发-缓存机制Informers和Reflector组件学习

    第三课 k8s源码学习和二次开发-缓存机制Informers和Reflector组件学习 tags: k8s 源码学习 categories: 源码学习 二次开发 文章目录 第三课 k8s源码学习和二 ...

  2. JAVA小项目实例源码—学习娱乐小助手

    代码地址如下: http://www.demodashi.com/demo/11456.html 一.程序实现 项目目录: MyJFrame:实现项目界面样式: AppProcess:实现调用api或 ...

  3. 第八课 k8s源码学习和二次开发原理篇-KubeBuilder使用和Controller-runtime原理

    第八课 k8s源码学习和二次开发原理篇-KubeBuilder使用和Controller-runtime原理 tags: k8s 源码学习 categories: 源码学习 二次开发 文章目录 第八课 ...

  4. 第四课 k8s源码学习和二次开发-DeltaFIFO和Indexer原理学习

    第四课 k8s源码学习和二次开发-DeltaFIFO和Indexer原理学习 tags: k8s 源码学习 categories: 源码学习 二次开发 文章目录 第四课 k8s源码学习和二次开发-De ...

  5. Java并发包源码学习之AQS框架(三)LockSupport和interrupt

    接着上一篇文章今天我们来介绍下LockSupport和Java中线程的中断(interrupt). 其实除了LockSupport,Java之初就有Object对象的wait和notify方法可以实现 ...

  6. 第十四课 k8s源码学习和二次开发原理篇-调度器原理

    第十四课 k8s源码学习和二次开发原理篇-调度器原理 tags: k8s 源码学习 categories: 源码学习 二次开发 文章目录 第十四课 k8s源码学习和二次开发原理篇-调度器原理 第一节 ...

  7. Java 中 Integer 源码学习之缓存池了解

    Java 中 Integer 源码学习之缓存池了解 面试题 new Integer(123) 与 Integer.valueOf(123) 的区别? new Integer(123) 每次都会新建一个 ...

  8. Java并发包源码学习系列:同步组件CountDownLatch源码解析

    文章目录 CountDownLatch概述 使用案例与基本思路 类图与基本结构 void await() boolean await(long timeout, TimeUnit unit) void ...

  9. Shiro源码学习之二

    接上一篇 Shiro源码学习之一 3.subject.login 进入login public void login(AuthenticationToken token) throws Authent ...

最新文章

  1. Module ‘celery‘ has no attribute ‘celery‘问题
  2. 通过SID查找历史执行的SQL语句
  3. 20171019_Python学习第四天
  4. python中列表用某个数字出现的次数_Python实现统计给定列表中指定数字出现次数的方法...
  5. spring AOP解析之xml方式详解
  6. 网络编程:TCP实现文件上传
  7. GraphicsMagick+im4java图片处理
  8. 【Kafka】Kafka客户端分配方案
  9. oc61--block
  10. python数据结构-链表
  11. tx2开发板接口详解_Linux CAN编程详解
  12. mysql中数据字典的定义,数据字典
  13. re正则表达式过滤标题特殊字符,只保留中英文及数字
  14. 【C/C++】共用体(union)
  15. 中小科技企业新蓝图,抓住资本新机遇!北京证券交易所要来了
  16. 电机驱动电路之H桥基本知识---Trinamic电机驱动芯片
  17. 【机器人学】冗余七自由度机械臂的解析解逆解算法
  18. 无人驾驶实战第一课--七月在线
  19. 自定义圆角矩形图片/圆形图片
  20. 分水岭变换的分割,watershed函数

热门文章

  1. Android 开源项目分类汇总(下)
  2. 使用POI读取EXCEL模板并填充数据,上传至腾讯云储存桶
  3. 图片base64转存本地url
  4. iOS判断当前设备机型 (包含至iPhone XS Max)
  5. 罗伯特索耶的写作六法则
  6. 【音乐系列】吉他学习入门基本知识
  7. CAD怎么转化成PDF?手机就可以轻松解决
  8. bim综合建模插件 进行碰撞检查只需六步!
  9. 坚鹏:中国邮政储蓄银行银行业同业竞争策略分析培训圆满结束
  10. Anaconda中GPU版本Pytorch 的whl 安装方法【2023.1最新最详细】(附anaconda以及cudacudnn安装教程)