Java IO流源码学习之二(Buffered字节流)
本文记录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字节流)相关推荐
- 第三课 k8s源码学习和二次开发-缓存机制Informers和Reflector组件学习
第三课 k8s源码学习和二次开发-缓存机制Informers和Reflector组件学习 tags: k8s 源码学习 categories: 源码学习 二次开发 文章目录 第三课 k8s源码学习和二 ...
- JAVA小项目实例源码—学习娱乐小助手
代码地址如下: http://www.demodashi.com/demo/11456.html 一.程序实现 项目目录: MyJFrame:实现项目界面样式: AppProcess:实现调用api或 ...
- 第八课 k8s源码学习和二次开发原理篇-KubeBuilder使用和Controller-runtime原理
第八课 k8s源码学习和二次开发原理篇-KubeBuilder使用和Controller-runtime原理 tags: k8s 源码学习 categories: 源码学习 二次开发 文章目录 第八课 ...
- 第四课 k8s源码学习和二次开发-DeltaFIFO和Indexer原理学习
第四课 k8s源码学习和二次开发-DeltaFIFO和Indexer原理学习 tags: k8s 源码学习 categories: 源码学习 二次开发 文章目录 第四课 k8s源码学习和二次开发-De ...
- Java并发包源码学习之AQS框架(三)LockSupport和interrupt
接着上一篇文章今天我们来介绍下LockSupport和Java中线程的中断(interrupt). 其实除了LockSupport,Java之初就有Object对象的wait和notify方法可以实现 ...
- 第十四课 k8s源码学习和二次开发原理篇-调度器原理
第十四课 k8s源码学习和二次开发原理篇-调度器原理 tags: k8s 源码学习 categories: 源码学习 二次开发 文章目录 第十四课 k8s源码学习和二次开发原理篇-调度器原理 第一节 ...
- Java 中 Integer 源码学习之缓存池了解
Java 中 Integer 源码学习之缓存池了解 面试题 new Integer(123) 与 Integer.valueOf(123) 的区别? new Integer(123) 每次都会新建一个 ...
- Java并发包源码学习系列:同步组件CountDownLatch源码解析
文章目录 CountDownLatch概述 使用案例与基本思路 类图与基本结构 void await() boolean await(long timeout, TimeUnit unit) void ...
- Shiro源码学习之二
接上一篇 Shiro源码学习之一 3.subject.login 进入login public void login(AuthenticationToken token) throws Authent ...
最新文章
- Module ‘celery‘ has no attribute ‘celery‘问题
- 通过SID查找历史执行的SQL语句
- 20171019_Python学习第四天
- python中列表用某个数字出现的次数_Python实现统计给定列表中指定数字出现次数的方法...
- spring AOP解析之xml方式详解
- 网络编程:TCP实现文件上传
- GraphicsMagick+im4java图片处理
- 【Kafka】Kafka客户端分配方案
- oc61--block
- python数据结构-链表
- tx2开发板接口详解_Linux CAN编程详解
- mysql中数据字典的定义,数据字典
- re正则表达式过滤标题特殊字符,只保留中英文及数字
- 【C/C++】共用体(union)
- 中小科技企业新蓝图,抓住资本新机遇!北京证券交易所要来了
- 电机驱动电路之H桥基本知识---Trinamic电机驱动芯片
- 【机器人学】冗余七自由度机械臂的解析解逆解算法
- 无人驾驶实战第一课--七月在线
- 自定义圆角矩形图片/圆形图片
- 分水岭变换的分割,watershed函数