java IO 篇之 BufferedInputStream

[b]一、主要方法及接口:[/b]

public synchronized int read();
private void fill();
public synchronized void mark(int readlimit);
public synchronized void reset();


[b]二、源码解读:[/b]
[u]1)public synchronized int read()[/u]
重载了父类FilterInputStream的read方法,主要作用还是按照字节从输入流中读取数据,但是第一次调用该方法时,会调用顶级类InputStream中的read(byte b[], int off, int len) 一次读取多个字节,并放到字节数组(defaultsize = 8192)中缓存起来,下次再读取的字节就是从缓存的字节数组中读取到的,直到已经读到最后一个缓存的字节,并且输入流中仍有未读取的数据,则继续读取长度为defaultsize的字节,并继续缓存在字节数组中,见如下代码

public synchronized int read() throws IOException {
if (pos >= count) {
fill();
if (pos >= count)
return -1;
}
return getBufIfOpen()[pos++] & 0xff;
}


private void fill() throws IOException {
byte[] buffer = getBufIfOpen();
if (markpos < 0)
pos = 0; /* no mark: throw away the buffer */
/*.......此处省略其他步骤*/

int n = getInIfOpen().read(buffer, pos, buffer.length - pos);
if (n > 0)
count = n + pos;

read(byte b[], int off, int len)的好处不用多说,自然是为了减少IO的访问次数,提高效率,个人感觉如果仅仅是为了缓存数据,减少IO的访问,大可不必再多此一举,提供BufferedInputStream这样的read方法,更多的秘密在于BufferedInputStream可以通过mark和reset的使用,缓存输入流中访问较为频繁的数据,达到在不访问IO的情况下,重读缓存中的数据。

[u]2)private void fill() [/u]
mark标记了待缓存数据的起始位置,fill方法根据mark的位置,通过System.arraycopy缓存部分数据

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;


[b]三、适用场景:[/b]
1、IO访问频率和次数较低的情况,可以一次读取多个字节
2、读取较大数据(size> 8192),并且待读取的数据需要频繁的被访问,通过mark和set方法,从mark位置开始缓存部分数据,在不访问IO的情况下,直接操作缓存数据
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值