public static void readFully(ByteBuff buf, FSDataInputStream dis, int length) throws IOException {
    final Span span = Span.current();
    if (!isByteBufferReadable(dis)) {
      // If InputStream does not support the ByteBuffer read, just read to heap and copy bytes to
      // the destination ByteBuff.
      byte[] heapBuf = new byte[length];
      IOUtils.readFully(dis, heapBuf, 0, length);
      span.addEvent("BlockIOUtils.readFully", getHeapBytesReadAttributes(span, length));
      copyToByteBuff(heapBuf, 0, length, buf);
      return;
    }
    int directBytesRead = 0, heapBytesRead = 0;
    ByteBuffer[] buffers = buf.nioByteBuffers();
    int remain = length;
    int idx = 0;
    ByteBuffer cur = buffers[idx];
    try {
      while (remain > 0) {
        while (!cur.hasRemaining()) {
          if (++idx >= buffers.length) {
            throw new IOException(
              "Not enough ByteBuffers to read the reminding " + remain + " " + "bytes");
          }
          cur = buffers[idx];
        }
        cur.limit(cur.position() + Math.min(remain, cur.remaining()));
        int bytesRead = dis.read(cur);
        if (bytesRead < 0) {
          throw new IOException(
            "Premature EOF from inputStream, but still need " + remain + " " + "bytes");
        }
        remain -= bytesRead;
        if (cur.isDirect()) {
          directBytesRead += bytesRead;
        } else {
          heapBytesRead += bytesRead;
        }
      }
    } finally {
      span.addEvent("BlockIOUtils.readFully",
        getDirectAndHeapBytesReadAttributes(span, directBytesRead, heapBytesRead));
    }
  }
Read length bytes into ByteBuffers directly.
@param buf    the destination {@link ByteBuff}
@param dis    the HDFS input stream which implement the ByteBufferReadable interface.
@param length bytes to read.
@throws IOException exception to throw if any error happen
hbase-common/src/main/java/org/apache/hadoop/hbase/io/util/BlockIOUtils.java