All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.github.stylesmile.file.LimitedInputStream Maven / Gradle / Ivy

package io.github.stylesmile.file;

import java.io.FilterInputStream;
import java.io.IOException;
import java.io.InputStream;

/**
 * The {@code LimitedInputStream} provides access to a limited number
 * of consecutive bytes from the underlying InputStream, starting at its
 * current position. If this limit is reached, it behaves as though the end
 * of stream has been reached (although the underlying stream remains open
 * and may contain additional data).
 */
public class LimitedInputStream extends FilterInputStream {

    protected long limit; // decremented when read, until it reaches zero
    protected boolean prematureEndException;

    /**
     * Constructs a LimitedInputStream with the given underlying
     * input stream and limit.
     *
     * @param in                    the underlying input stream
     * @param limit                 the maximum number of bytes that may be consumed from
     *                              the underlying stream before this stream ends. If zero or
     *                              negative, this stream will be at its end from initialization.
     * @param prematureEndException specifies the stream's behavior when
     *                              the underlying stream end is reached before the limit is
     *                              reached: if true, an exception is thrown, otherwise this
     *                              stream reaches its end as well (i.e. read() returns -1)
     * @throws NullPointerException if the given stream is null
     */
    public LimitedInputStream(InputStream in, long limit, boolean prematureEndException) {
        super(in);
        if (in == null) {
            throw new NullPointerException("input stream is null");
        }
        this.limit = limit < 0 ? 0 : limit;
        this.prematureEndException = prematureEndException;
    }
    public LimitedInputStream(InputStream in, long limit) {
        super(in);
        if (in == null) {
            throw new NullPointerException("input stream is null");
        }
        this.limit = limit < 0 ? 0 : limit;
    }

    @Override
    public int read() throws IOException {
        int res = limit == 0 ? -1 : in.read();
        if (res < 0 && limit > 0 && prematureEndException)
            throw new IOException("unexpected end of stream");
        limit = res < 0 ? 0 : limit - 1;
        return res;
    }

    @Override
    public int read(byte[] b, int off, int len) throws IOException {
        int res = limit == 0 ? -1 : in.read(b, off, len > limit ? (int) limit : len);
        if (res < 0 && limit > 0 && prematureEndException)
            throw new IOException("unexpected end of stream");
        limit = res < 0 ? 0 : limit - res;
        return res;
    }

    @Override
    public long skip(long len) throws IOException {
        long res = in.skip(len > limit ? limit : len);
        limit -= res;
        return res;
    }

    @Override
    public int available() throws IOException {
        int res = in.available();
        return res > limit ? (int) limit : res;
    }

    @Override
    public boolean markSupported() {
        return false;
    }

    @Override
    public void close() {
        limit = 0; // end this stream, but don't close the underlying stream
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy