code: public synchronized int read(byte[] b, int off, int len) throws IOException {
      // parameter check
      if ((off | len | (off + len) | (b.length - (off + len))) < 0) {
        throw new IndexOutOfBoundsException();
      }
  
      int n = 0;
      for (;;) {
        int nread = read1(b, off + n, len - n);
        if (nread <= 0) 
          return (n == 0) ? nread : n;
        n += nread;
        if (n >= len)
          return n;
      }
    }
docs: Read checksum verified bytes from this byte-input stream into
  the specified byte array, starting at the given offset.
  
  <p> This method implements the general contract of the corresponding
  <code>{@link InputStream#read(byte[], int, int) read}</code> method of
  the <code>{@link InputStream}</code> class.  As an additional
  convenience, it attempts to read as many bytes as possible by repeatedly
  invoking the <code>read</code> method of the underlying stream.  This
  iterated <code>read</code> continues until one of the following
  conditions becomes true: <ul>
  
  <li> The specified number of bytes have been read,
  
  <li> The <code>read</code> method of the underlying stream returns
  <code>-1</code>, indicating end-of-file.
  
  </ul> If the first <code>read</code> on the underlying stream returns
  <code>-1</code> to indicate end-of-file then this method returns
  <code>-1</code>.  Otherwise this method returns the number of bytes
  actually read.
  
  @param      b     destination buffer.
  @param      off   offset at which to start storing bytes.
  @param      len   maximum number of bytes to read.
  @return     the number of bytes read, or <code>-1</code> if the end of
  the stream has been reached.
  @exception  IOException  if an I/O error occurs.
  ChecksumException if any checksum error occurs