jooby/src/main/java/org/jooby/internal/ReaderInputStream.java
@Override
  public int read(final byte[] b, int off, int len) throws IOException {
    int read = 0;
    while (len > 0) {
      if (encoderOut.position() > 0) {
        encoderOut.flip();
        int c = Math.min(encoderOut.remaining(), len);
        encoderOut.get(b, off, c);
        off += c;
        len -= c;
        read += c;
        encoderOut.compact();
      } else {
        if (!endOfInput && (lastCoderResult == null || lastCoderResult.isUnderflow())) {
          encoderIn.compact();
          int position = encoderIn.position();
          // We don't use Reader#read(CharBuffer) here because it is more efficient
          // to write directly to the underlying char array (the default implementation
          // copies data to a temporary char array).
          int c = reader.read(encoderIn.array(), position, encoderIn.remaining());
          if (c == -1) {
            endOfInput = true;
          } else {
            encoderIn.position(position + c);
          }
          encoderIn.flip();
        }
        lastCoderResult = encoder.encode(encoderIn, encoderOut, endOfInput);
        if (endOfInput && encoderOut.position() == 0) {
          break;
        }
      }
    }
    return read == 0 && endOfInput ? -1 : read;
  }
@Override
  public int read(final byte[] b, int off, int len) throws IOException {
    int read = 0;
    while (len > 0) {
      if (encoderOut.position() > 0) {
        encoderOut.flip();
        int c = Math.min(encoderOut.remaining(), len);
        encoderOut.get(b, off, c);
        off += c;
        len -= c;
        read += c;
        encoderOut.compact();
      } else {
        if (!endOfInput && (lastCoderResult == null || lastCoderResult.isUnderflow())) {
          encoderIn.compact();
          int position = encoderIn.position();
          // We don't use Reader#read(CharBuffer) here because it is more efficient
          // to write directly to the underlying char array (the default implementation
          // copies data to a temporary char array).
          int c = reader.read(encoderIn.array(), position, encoderIn.remaining());
          if (c == -1) {
            endOfInput = true;
          } else {
            encoderIn.position(position + c);
          }
          encoderIn.flip();
        }
        lastCoderResult = encoder.encode(encoderIn, encoderOut, endOfInput);
        if (endOfInput && encoderOut.position() == 0) {
          break;
        }
      }
    }
    return read == 0 && endOfInput ? -1 : read;
  }
Read the specified number of bytes into an array.

@param b the byte array to read into
@param off the offset to start reading bytes into
@param len the number of bytes to read
@return the number of bytes read or <code>-1</code> if the end of the stream has been reached
@throws IOException if an I/O error occurs