[b]一、主要方法及接口:[/b]
[b]二、源码解读:[/b]
[u]1)public synchronized int read()[/u]
重载了父类FilterInputStream的read方法,主要作用还是按照字节从输入流中读取数据,但是第一次调用该方法时,会调用顶级类InputStream中的read(byte b[], int off, int len) 一次读取多个字节,并放到字节数组(defaultsize = 8192)中缓存起来,下次再读取的字节就是从缓存的字节数组中读取到的,直到已经读到最后一个缓存的字节,并且输入流中仍有未读取的数据,则继续读取长度为defaultsize的字节,并继续缓存在字节数组中,见如下代码
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缓存部分数据
[b]三、适用场景:[/b]
1、IO访问频率和次数较低的情况,可以一次读取多个字节
2、读取较大数据(size> 8192),并且待读取的数据需要频繁的被访问,通过mark和set方法,从mark位置开始缓存部分数据,在不访问IO的情况下,直接操作缓存数据
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的情况下,直接操作缓存数据