@Override
    public int read(byte[] b, int off, int len) throws IOException {
        if (b == null) {
            throw new NullPointerException(ERROR_NULL_BYTES);
        } else if (buffer != null && buffer.hasArray() && buffer.array() == b) {
            // in case b is the byte array return from ClickHouseByteBuffer.array()
            throw new IllegalArgumentException(ERROR_REUSE_BUFFER);
        } else if (off < 0 || len < 0 || len > b.length - off) {
            throw new IndexOutOfBoundsException();
        } else if (len == 0) {
            return 0;
        }
        ensureOpen();

        int offset = off;
        while (len > 0) {
            if (buffer == ClickHouseByteBuffer.EMPTY_BUFFER) {
                return off > offset ? off - offset : -1;
            }

            int remain = buffer.remaining();
            if (remain >= len) {
                buffer.get(b, off, len);
                off += len;
                break;
            } else {
                buffer.get(b, off, remain);
                off += remain;
                len -= remain;
                updateBuffer();
            }
        }

        return off - offset;
    }
Update inner buffer as needed.

@return remaining bytes in buffer
@throws IOException when failed to update buffer
clickhouse-data/src/main/java/com/clickhouse/data/stream/AbstractByteBufferInputStream.java