private void readDataDescr() throws IOException {
   if (readLeInt() != EXTSIG) throw new ZipException("Data descriptor signature not found");
   entry.setCrc(readLeInt() & 0xffffffffL);
   csize = readLeInt();
   size = readLeInt();
   entry.setSize(size & 0xffffffffL);
   entry.setCompressedSize(csize & 0xffffffffL);
 }
  /**
   * Reads a block of bytes from the current zip entry.
   *
   * @return the number of bytes read (may be smaller, even before EOF), or -1 on EOF.
   * @exception IOException if a i/o error occured.
   * @exception ZipException if the deflated stream is corrupted.
   */
  public int read(byte[] b, int off, int len) throws IOException {
    if (len == 0) return 0;
    if (crc == null) throw new IOException("Stream closed.");
    if (entry == null) return -1;
    boolean finished = false;
    switch (method) {
      case ZipOutputStream.DEFLATED:
        len = super.read(b, off, len);
        if (len < 0) {
          if (!inf.finished()) throw new ZipException("Inflater not finished!?");
          avail = inf.getRemaining();
          if ((flags & 8) != 0) readDataDescr();

          if (inf.getTotalIn() != csize || inf.getTotalOut() != size)
            throw new ZipException(
                "size mismatch: "
                    + csize
                    + ";"
                    + size
                    + " <-> "
                    + inf.getTotalIn()
                    + ";"
                    + inf.getTotalOut());
          inf.reset();
          finished = true;
        }
        break;

      case ZipOutputStream.STORED:
        if (len > csize && csize >= 0) len = csize;

        len = readBuf(b, off, len);
        if (len > 0) {
          csize -= len;
          size -= len;
        }

        if (csize == 0) finished = true;
        else if (len < 0) throw new ZipException("EOF in stored block");
        break;
    }

    if (len > 0) crc.update(b, off, len);

    if (finished) {
      if ((crc.getValue() & 0xffffffffL) != entry.getCrc()) throw new ZipException("CRC mismatch");
      crc.reset();
      entry = null;
      entryAtEOF = true;
    }
    return len;
  }
  /**
   * Open the next entry from the zip archive, and return its description. If the previous entry
   * wasn't closed, this method will close it.
   */
  public ZipEntry getNextEntry() throws IOException {
    if (crc == null) throw new IOException("Stream closed.");
    if (entry != null) closeEntry();

    int header = readLeInt();
    if (header == CENSIG) {
      /* Central Header reached. */
      close();
      return null;
    }
    if (header != LOCSIG)
      throw new ZipException("Wrong Local header signature: " + Integer.toHexString(header));
    /* skip version */
    readLeShort();
    flags = readLeShort();
    method = readLeShort();
    int dostime = readLeInt();
    int crc = readLeInt();
    csize = readLeInt();
    size = readLeInt();
    int nameLen = readLeShort();
    int extraLen = readLeShort();

    if (method == ZipOutputStream.STORED && csize != size)
      throw new ZipException("Stored, but compressed != uncompressed");

    byte[] buffer = new byte[nameLen];
    readFully(buffer);
    String name;
    try {
      name = new String(buffer, "UTF-8");
    } catch (UnsupportedEncodingException uee) {
      throw new Error(uee.toString());
    }

    entry = createZipEntry(name);
    entryAtEOF = false;
    entry.setMethod(method);
    if ((flags & 8) == 0) {
      entry.setCrc(crc & 0xffffffffL);
      entry.setSize(size & 0xffffffffL);
      entry.setCompressedSize(csize & 0xffffffffL);
    }
    entry.setDOSTime(dostime);
    if (extraLen > 0) {
      byte[] extra = new byte[extraLen];
      readFully(extra);
      entry.setExtra(extra);
    }

    if (method == ZipOutputStream.DEFLATED && avail > 0) {
      System.arraycopy(buf, len - avail, buf, 0, avail);
      len = avail;
      avail = 0;
      inf.setInput(buf, 0, len);
    }
    return entry;
  }