/**
  * Reads uncompressed data into an array of bytes. If <code>len</code> is not zero, the method
  * will block until some input can be decompressed; otherwise, no bytes are read and <code>0
  * </code> is returned.
  *
  * @param b the buffer into which the data is read
  * @param off the start offset in the destination array <code>b</code>
  * @param len the maximum number of bytes read
  * @return the actual number of bytes read, or -1 if the end of the compressed input is reached or
  *     a preset dictionary is needed
  * @exception NullPointerException If <code>b</code> is <code>null</code>.
  * @exception IndexOutOfBoundsException If <code>off</code> is negative, <code>len</code> is
  *     negative, or <code>len</code> is greater than <code>b.length - off</code>
  * @exception ZipException if a ZIP format error has occurred
  * @exception IOException if an I/O error has occurred
  */
 public int read(byte[] b, int off, int len) throws IOException {
   ensureOpen();
   if (b == null) {
     throw new NullPointerException();
   } else if (off < 0 || len < 0 || len > b.length - off) {
     throw new IndexOutOfBoundsException();
   } else if (len == 0) {
     return 0;
   }
   try {
     int n;
     while ((n = inf.inflate(b, off, len)) == 0) {
       if (inf.finished() || inf.needsDictionary()) {
         reachEOF = true;
         return -1;
       }
       if (inf.needsInput()) {
         fill();
       }
     }
     return n;
   } catch (DataFormatException e) {
     String s = e.getMessage();
     throw new ZipException(s != null ? s : "Invalid ZLIB data format");
   }
 }