@Override
    public int read(byte[] b, int off, int len) throws IOException {
        abortIfNeeded();
        if (b == null) {
            throw new NullPointerException();
        } else if (off < 0 || len < 0 || len > b.length - off) {
            throw new IndexOutOfBoundsException();
        } else if (len == 0) {
            return 0;
        }

        if (null == currentChunkIterator
                || !currentChunkIterator.hasNext()) {
            if (isTerminating)
                return -1;
            else {
                isTerminating = setUpNextChunk();
            }
        }

        int count = currentChunkIterator.read(b, off, len);
        if (count > 0) {
            isAtStart = false;
            if (log.isTraceEnabled())
                log.trace(count + " byte read from the stream.");
        }
        return count;
    }
A wrapper of InputStream that implements pseudo-chunked-encoding.
Each chunk will be buffered for the calculation of the chunk signature
which is added at the head of each chunk.<br>
The default chunk size cannot be customized, since we need to calculate
the expected encoded stream length before reading the wrapped stream.<br>
This class will use the mark() & reset() of the wrapped InputStream if they
are supported, otherwise it will create a buffer for bytes read from
the wrapped stream.
@param in
            The original InputStream.
@param maxBufferSize
            Maximum number of bytes buffered by this class.
@param kSigning
            Signing key.
@param datetime
            Datetime, as used in SigV4.
@param keyPath
            Keypath/Scope, as used in SigV4.
@param headerSignature
            The signature of the signed headers. This will be used for
            calculating the signature of the first chunk.
@param aws4Signer
            The AWS4Signer used for hashing and signing.
aws-java-sdk-s3/src/main/java/com/amazonaws/auth/AwsChunkedEncodingInputStream.java