BufferedInputStream | BufferedOutputStream

BufferedInputStream

BufferedInputStream 是一个包装类,通过持有inputstream的引用,并在原有read方法基础上添加buffer数组缓存,实现了缓冲的目的。

构造函数,需要传入实际的inputstream,默认缓冲数组大小8192,8kb
	 public BufferedInputStream(InputStream in) {
     
        this(in, DEFAULT_BUFFER_SIZE);
    }

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~`
  当前缓冲区中数据长度
  protected int count;
  下一次读取位置的下标
  protected int pos;
  调用mark方法后,记录当前pos的位置
  protected int markpos = -1;
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    read方法,一次读取一个字节,内部有缓冲
    public synchronized int read() throws IOException {
     
    //如果下一次读取的位置,超出了缓冲区中的数据
        if (pos >= count) {
     
        //读取数据到buffer数组
            fill();
            if (pos >= count)
                return -1;
        }
        return getBufIfOpen()[pos++] & 0xff;
    }

	向缓冲区中写数据
    private void fill() throws IOException {
     
    	//获取当前缓冲数组
        byte[] buffer = getBufIfOpen();
        //如果未执行mark,pos重置为0
        if (markpos < 0)
            pos = 0;
        //如果缓冲区满了            
        else if (pos >= buffer.length)
            if (markpos > 0) 
            	//计算markops 及之后的数据长度
                int sz = pos - markpos;
                //缓冲区数据从markops开始,拷贝sz长度的数据,到下标为0开始的地方
                System.arraycopy(buffer, markpos, buffer, 0, sz);
                //记录下一次读取位置
                pos = sz;
                markpos = 0;
            }
            //重置pos,markpos 
			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 {
        
             //如果pos<=最大缓冲/2,nsz为pos的2倍,否则nsz为最大缓冲区长度        
                int nsz = (pos <= MAX_BUFFER_SIZE - pos) ?
                        pos * 2 : MAX_BUFFER_SIZE;
                  //如果nsz超过标记的limit,扩容为marklimit
                if (nsz > marklimit)
                    nsz = marklimit;
                byte[] nbuf = new byte[nsz];
                //旧数组数据考到新数组中
                System.arraycopy(buffer, 0, nbuf, 0, pos);
                if (!U.compareAndSetObject(this, BUF_OFFSET, 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;
    }
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
read 方法,读取数据到b数组,从off开始,读len个长度
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;
            //累计的数据>=len,b已经读满了,返回
            if (n >= len)
                return n;
            // 流中数据已经读完了,返回
            InputStream input = in;
            if (input != null && input.available() <= 0)
                return n;
        }
    }
    
     private int read1(byte[] b, int off, int len) throws IOException {
     
     	//计算缓冲区中可用数据
        int avail = count - pos;
        //avail<=0,说明缓冲区已经读完了,如果缓冲区还有数据,会先返回缓冲区中数据,
        if (avail <= 0) {
     
        	//len>=缓冲区长度 并且 markops <0,直接在流中读取,不再缓存
            if (len >= getBufIfOpen().length && markpos < 0) {
     
                return getInIfOpen().read(b, off, len);
            }
            //读取流数据,写入缓冲区
            fill();
            //重新计算缓冲区中可用数据
            avail = count - pos;
            if (avail <= 0) return -1;
        }
        //与len进行对比,算出需要读取的数据长度
        int cnt = (avail < len) ? avail : len;
        //拷贝数据
        System.arraycopy(getBufIfOpen(), pos, b, off, cnt);
        //pos 移到下一次需要读取的位置
        pos += cnt;
        return cnt;
    }

BufferedOutputStream

BufferedOutputStream是一个带有缓冲功能的输出流,通过内部具体的outputstream实现读写,

	缓冲区
	protected byte buf[];
	缓冲区中有效数据长度
    protected int count;
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
构造函数,默认缓冲区8M
   public BufferedOutputStream(OutputStream out) {
     
        this(out, 8192);
    }
   public BufferedOutputStream(OutputStream out, int size) {
     
        super(out);
        if (size <= 0) {
     
            throw new IllegalArgumentException("Buffer size <= 0");
        }
        buf = new byte[size];
    }
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    
    public synchronized void write(int b) throws IOException {
     
    	//缓冲区满了,进行实际写入操作
        if (count >= buf.length) {
     
            flushBuffer();
        }
        将数据写入缓冲区
        buf[count++] = (byte)b;
    }
    
     private void flushBuffer() throws IOException {
     
        if (count > 0) {
     
        	//将缓冲区中数据写入,将count置位0,逻辑清空缓冲区
            out.write(buf, 0, count);
            count = 0;
        }
    }
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    public synchronized void flush() throws IOException {
     
    	清空缓冲区,写入数据
        flushBuffer();
        //	outputstream中 flush 方法是空实现,不进行任何操作
        out.flush();
    }

你可能感兴趣的:(java,i/o)