1. BufferedInputStream的基本原理
BuffredInputStream存在的意义在于其提供了一个内部缓冲区,当read的的时候先一次性的把byte读取到内部的缓冲区,以后每次调用read(byte[])实际是从缓冲区 copy数据。缓冲区的大小可以通过BufferedInputStream(InputStream in, int size)构造函数设置,默认大小8192。
2.BufferedInputStream的实现
注意read方法是同步的:
public synchronized int read(byte b[], int off, int len) throws IOException { getBufIfOpen(); // Check for closed stream if ((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, return InputStream input = in; if (input != null && input.available() <= 0) return n; } }
实现都委托给里read1()
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, and if there is no mark/reset activity, do not bother to copy the bytes into the local buffer. In this way buffered streams will cascade 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; }
fill:
/** * Fills the buffer with more data, taking into account * shuffling and other tricks for dealing with marks. * Assumes that it is being called by a synchronized method. * This method also assumes that all data has already been read in, * hence pos > count. */ 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 { /* grow buffer */ int nsz = pos * 2; 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; }
3.BufferedInputStream对buffer的并发保护
buffreedInputStream是有状态的,需要考虑线程安全的问题,那么来看看它是如何保护buffer。首先
buf被定义为volatile,并且通过AtomicReferenceFieldUpdater来保护。
/** * The internal buffer array where the data is stored. When necessary, * it may be replaced by another array of * a different size. */ protected volatile byte buf[]; /** * Atomic updater to provide compareAndSet for buf. This is * necessary because closes can be asynchronous. We use nullness * of buf[] as primary indicator that this stream is closed. (The * "in" field is also nulled out on close.) */ private static final AtomicReferenceFieldUpdater<BufferedInputStream, byte[]> bufUpdater = AtomicReferenceFieldUpdater.newUpdater (BufferedInputStream.class, byte[].class, "buf");AtomicReferenceFieldUpdater基于反射的实用工具,可以对指定类的指定
volatile
字段进行原子更新。用法:
相关推荐
BufferedInputStream源码分析图
BufferedInputStream 是缓冲输入流。它继承于FilterInputStream。 BufferedInputStream 的作用是为另一个输入流添加一些功能,例如,提供“缓冲功能”以及支持“mark()标记”和“reset()重置方法”。
主要为大家详细介绍了BufferedInputStream缓冲输入流的相关资料,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
BufferedInputStream的用法1---马克-to-win java视频
BufferedInputStream的用法3---马克-to-win java视频缓存输字节流
文本的保存(写入磁盘的时候),字节流 : BufferedInputStream 比 InputStream 性能会比较好点(本人测试过,有实验数据)
java代码,使用字符流读取文件,让新手了解字符流,以及新手学习字符流。在学习过程中进步,用java中的BufferedOutputStream.
jdk api-BufferedInputStream基础、应用、实战
BufferedInputStream 的增强版,不使用 available()。 BuffereInputStream 的自定义实现,它根本不调用嵌套流的方法“available()”。 对于那些不阻止它或实现错误的 InputStreams 来说,这可能是合理和有帮助的 ...
BufferedInputStream的用法2---马克-to-win java啊视频
主要介绍了Java IO学习之缓冲输入流(BufferedInputStream)的相关资料,需要的朋友可以参考下
BufferedInputStream和BufferedOutputStream分别继承于FilterInputStream和FilterOutputStream,代表着缓冲区的输入输出,这里我们就来看一下Java中的BufferedInputStream与BufferedOutputStream使用示例:
喜欢在下面评论区扣1支持下呗 字节缓冲输出流: BufferedOutputStream (OutputStream out) public class BufferStreamDemo { public static void main(String[] args) throws IOException { //字节缓冲输出流: ...
BufferedInputStream bufferedInputStream = new BufferedInputStream(fileInputStream); //创建播放器对象,把文件的缓冲流传入进去 player = new Player(bufferedInputStream); ...
java 压缩/解压 .zip/.rar/.tar 文件,大家一起讨论,学习 已实现zip压缩/解压,rar解压
使用BufferedInputStream字节流,以及StringBuiler技术实现字节的逐行读取。即字节流的readline功能。BufferedInputStream bufferedInputStream=new BufferedInputStream(new FileInputStream(file));
一个还好的Android手机无线(WIFI)连接无线路由实现局域网 连接电脑后,进行文件传送的Socket/TCP实例。 需要手机WIFI连接局域网,并设定IP地址,地址可在程序文件找到,或者自行对应修改,需要统一。
NULL 博文链接:https://shuangpan-zhang.iteye.com/blog/1205530
BufferedInputStream buffer = new BufferedInputStream(new FileInputStream(music)); player = new Player(buffer); player.play(); } public static void main(String[] args) throws JavaLayerException {...