dap4/d4lib/src/main/java/dap4/dap4lib/ChunkInputStream.java
public int
    read(byte[] buf, int off, int len)
            throws IOException
    {
        // Sanity check
        if(off < 0 || len < 0)
            throw new IndexOutOfBoundsException();// Runtime
        if(off >= buf.length || buf.length < (off + len))
            throw new IndexOutOfBoundsException(); //Runtime
        if(requestmode == RequestMode.DMR)
            throw new UnsupportedOperationException("Attempt to read databuffer when DMR only"); // Runtime

        // Attempt to read len bytes out of a sequence of chunks
        int count = len;
        int pos = off;
        while(count > 0) {
            if(avail <= 0) {
                if((flags & DapUtil.CHUNK_END) != 0
                        || !readHeader(input))
                    return (len - count); // return # databuffer read
                // See if we have an error chunk,
                // and if so, turn it into an exception
                if((flags & DapUtil.CHUNK_ERROR) != 0) {
                    String document = readError();
                    throwError(document);
                }
            } else {
                int actual = (this.avail < count ? this.avail : count);
                int red = input.read(buf, pos, actual);
                if(red < 0)
                    throw new IOException("Unexpected EOF");
                pos += red;
                count -= red;
                this.avail -= red;
            }
        }
        return len;
    }
public int
    read(byte[] buf, int off, int len)
            throws IOException
    {
        // Sanity check
        if(off < 0 || len < 0)
            throw new IndexOutOfBoundsException();// Runtime
        if(off >= buf.length || buf.length < (off + len))
            throw new IndexOutOfBoundsException(); //Runtime
        if(requestmode == RequestMode.DMR)
            throw new UnsupportedOperationException("Attempt to read databuffer when DMR only"); // Runtime

        // Attempt to read len bytes out of a sequence of chunks
        int count = len;
        int pos = off;
        while(count > 0) {
            if(avail <= 0) {
                if((flags & DapUtil.CHUNK_END) != 0
                        || !readHeader(input))
                    return (len - count); // return # databuffer read
                // See if we have an error chunk,
                // and if so, turn it into an exception
                if((flags & DapUtil.CHUNK_ERROR) != 0) {
                    String document = readError();
                    throwError(document);
                }
            } else {
                int actual = (this.avail < count ? this.avail : count);
                int red = input.read(buf, pos, actual);
                if(red < 0)
                    throw new IOException("Unexpected EOF");
                pos += red;
                count -= red;
                this.avail -= red;
            }
        }
        return len;
    }
Reads up to len databuffer of databuffer from the input stream into an
array of databuffer. An attempt is made to read as many as len
databuffer, but a smaller number may be read. The number of databuffer
actually read is returned as an integer.

@param buf the byte array into which databuffer is read
@param off the offset in the byte array at which to write
@param len the amount to read
@return the actual number of databuffer read
@throws IOException