BufferedInputStream内用有一个很重要的private函数fill(),这个函数的原型如下:
[code="java"] private void fill() throws IOException {
byte[] buffer = getBufIfOpen();
if (markpos = 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;
}
众所周知,BufferedInputStream会缓存一部分数据(默认8K),这个函数的作用就是读取更多的数据到缓存,必要的时候会扩大缓存的内容。
讲解这个函数前,先了解一下BufferedInputStream中一些字段的含义:
如图所示,矩形的长度表示buf的长度,count表示buf中的可读数据长度,pos表示当前已读取到的位置,markpos表示上一次调用mark函数时pos的位置,如果没调用过mark函数,则为-1。marklength的含义是,在调用reset函数的时候,marklength范围内的缓存必须被保留,注意marklength不能大于marklimit(marklimit是缓存中容许保留的最大长度)。
下面开始解读这个函数:
getBufIfOpen是获取当前buf的引用;
if (markpos < 0)
pos = 0;
这句说明buf中没做过标记,没有数据需要保留,可以直接清空缓存buf;
else if (pos >= buffer.length)
这一句有两层含义:首先说明缓存中可能(注意,是可能)有数据需要保留,
同时说明缓存中已经没有可用的空间;
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;
}
这一段代码,是处理缓存中确实有数据要保留的情况,首先计算需要保留的数据
占用的空间int sz = pos - markpos;
然后将它们copy到缓存的头部System.arraycopy(buffer, markpos, buffer, 0, sz);
再将当前位置设置到(pos-markpos),markpos设置到缓存的起始位置;
else if (buffer.length >= marklimit) {
markpos = -1; /* buffer got too big, invalidate mark */
pos = 0; /* drop buffer contents */
}
如果marklimit的值小于缓存的长度,说明buffer很大,从内存使用的角度考虑,此时
不宜再增大缓存的容量,在这种情形下直接丢弃buf中的已有内容;
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;
}
如果缓存的容量不是很大,则扩大一倍(int nsz = pos * 2),因为此时markpos为-1,
所以将0到pos的数据保留(System.arraycopy(buffer, 0, nbuf, 0, pos)),下面的if
语句是使用了原子变量引用更新,确保多线程环境下内存的可见性;
count = pos;
int n = getInIfOpen().read(buffer, pos, buffer.length - pos);
if (n > 0)
count = n + pos;
上面的代码是将缓存尽量的读满,并重新设置可读数据的长度count。
- 大小: 20.5 KB
分享到:
相关推荐
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和BufferedOutputStream分别继承于FilterInputStream和FilterOutputStream,代表着缓冲区的输入输出,这里我们就来看一下Java中的BufferedInputStream与BufferedOutputStream使用示例:
BufferedInputStream的用法2---马克-to-win java啊视频
主要介绍了Java IO学习之缓冲输入流(BufferedInputStream)的相关资料,需要的朋友可以参考下
IO从大的方向上分为字节流和字符流,包括四个抽象类: 1、输入:Reader, InputStream类型的子类(字符,字节) ...1) BufferedInputStream:带缓冲的输入流,构造函数有: BufferedInputStream(InputStream in)
喜欢在下面评论区扣1支持下呗 字节缓冲输出流: BufferedOutputStream (OutputStream out) public class BufferStreamDemo { public static void main(String[] args) throws IOException { //字节缓冲输出流: ...
使用java.util.PropertyResourceBundle类的构造函数 示例: InputStream in = new BufferedInputStream(new FileInputStream(name)); ResourceBundle rb = new PropertyResourceBundle(in); 4。使用class变量...
BufferedInputStream bufferedInputStream = new BufferedInputStream(fileInputStream); //创建播放器对象,把文件的缓冲流传入进去 player = new Player(bufferedInputStream); ...
java中实现复制文件和文件夹 public static void copyFile(File sourceFile,File targetFile) throws IOException{ // 新建文件输入流并对它进行缓冲 FileInputStream input = new FileInputStream(sourceFile)...
java 压缩/解压 .zip/.rar/.tar 文件,大家一起讨论,学习 已实现zip压缩/解压,rar解压
使用BufferedInputStream字节流,以及StringBuiler技术实现字节的逐行读取。即字节流的readline功能。BufferedInputStream bufferedInputStream=new BufferedInputStream(new FileInputStream(file));
一个还好的Android手机无线(WIFI)连接无线路由实现局域网 连接电脑后,进行文件传送的Socket/TCP实例。 需要手机WIFI连接局域网,并设定IP地址,地址可在程序文件找到,或者自行对应修改,需要统一。