BufferedInputStream/BufferedOutputStream
BufferedInputStream:
public synchronized int read() throws IOException int res=bis.read(); System.out.println((char)res)
调用一次,取一次值,并游标向前走一位;返回值为unicode码
public synchronized int read(byte b[], int off, int len) throws IOException byte[] buff=new byte[LEN]; int res=bis.read(buff,0,LEN); System.out.println(new String(buff,0,res));
调用一次 取LEN个值,并游标向前走LEN位,数据保存在字节数组中,返回值是数据个数;
public synchronized int available() throws IOException
返回目标文件大小, 底层实现
public synchronized void mark(int readlimit) public synchronized void reset() throws IOException
mark用来标记断点(下标)并传入一个readlimit (缓冲流最大限制)
reset 将返回到断点重新读取数据
根据源码解读:
public synchronized void mark(int readlimit) { marklimit = readlimit; markpos = pos; } public synchronized void reset() throws IOException { getBufIfOpen(); // Cause exception if closed if (markpos < 0) throw new IOException("Resetting to invalid mark"); pos = markpos; }
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; }
1、调用mark 并传入int类型参数赋值给marklimit,同时将pos赋值给markpos;
2、在读取数据过程中,在没调用reset前,pos会持续自增;
3、 在缓冲区中数据读取完后,会再次调用fill方法,使缓冲区扩大一倍,然后pos继续自增
接下来有三种运行路线
1、缓冲区大小超过marklimit时,调用reset时,会抛异常,因为markpos=-1;
2、缓冲区大小超过最大缓冲区大小,直接抛异常
3、缓冲区大小没有超过marklimit,调用reset,缓冲区大小回到初始值大小,将markpos复制给pos,返回到标记点,重新读取数据;
还有查看源码发现,如果缓冲区大小没有超过marklimit,,那么这个标记一直存在,知道缓冲close;没有找到去掉标记的方法;
BufferedOutputStream:
public synchronized void write(int b) throws IOException public synchronized void write(byte b[], int off, int len) throws IOException public synchronized void flush() throws IOException private void flushBuffer() throws IOException