private void positionAtCentralDirectory(@NotNull ThreeState isZip64) throws IOException {
    boolean found = false;
    long off = myArchive.length() - MIN_EOCD_SIZE;
    if (off >= 0) {
      myArchive.seek(off);
      byte[] sig = JBZipOutputStream.EOCD_SIG;
      int curr = myArchive.read();
      while (curr != -1) {
        if (curr == sig[0]) {
          curr = myArchive.read();
          if (curr == sig[1]) {
            curr = myArchive.read();
            if (curr == sig[2]) {
              curr = myArchive.read();
              if (curr == sig[3]) {
                found = true;
                break;
              }
            }
          }
        }
        myArchive.seek(--off);
        curr = myArchive.read();
      }
    }
    if (!found) {
      throw new ZipException("archive is not a ZIP archive");
    }

    boolean searchForZip64EOCD = myArchive.getFilePointer() > ZIP64_EOCDL_LENGTH;
    if (searchForZip64EOCD) {
      myArchive.seek(myArchive.getFilePointer() - ZIP64_EOCDL_LENGTH - WORD);
      myIsZip64 = Arrays.equals(readBytes(WORD), JBZipOutputStream.ZIP64_EOCD_LOC_SIG);
    }

    if (myIsZip64) {
      if (isZip64.equals(ThreeState.NO)) {
        throw new IOException("Non ZIP64 archive was requested but it is a ZIP64 archive");
      }

      myArchive.skipBytes(ZIP64_EOCDL_LOCATOR_OFFSET - WORD);
      myArchive.seek(ZipUInt64.getLongValue(readBytes(DWORD)));
      if (!Arrays.equals(readBytes(WORD), JBZipOutputStream.ZIP64_EOCD_SIG)) {
        throw new IOException("archive is not a ZIP64 archive");
      }

      myArchive.skipBytes(ZIP64_EOCD_CFD_LOCATOR_OFFSET
                          - WORD /* signature has already been read */);
      long value = ZipUInt64.getLongValue(readBytes(DWORD));
      currentCfdOffset = value;
      myArchive.seek(value);
    }
    else {
      if (isZip64.equals(ThreeState.YES)) {
        throw new IOException("ZIP64 archive was requested but it is not a ZIP64 archive");
      }

      myArchive.seek(off + CFD_LOCATOR_OFFSET);
      byte[] cfdOffset = new byte[WORD];
      myArchive.readFully(cfdOffset);
      currentCfdOffset = ZipLong.getValue(cfdOffset);
      myArchive.seek(currentCfdOffset);
    }
  }
private void positionAtCentralDirectory(@NotNull ThreeState isZip64)