Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
329 views
in Technique[技术] by (71.8m points)

java - Copy InputStream, abort operation if size exceeds limit

I tried to copy an InputStream to a File, and abort the copy if the size of InputStream is greater than 1MB. In Java7, I wrote code as below:

public void copy(InputStream input, Path target) {
    OutputStream out = Files.newOutputStream(target,
            StandardOpenOption.CREATE_NEW, StandardOpenOption.WRITE);
    boolean isExceed = false;
    try {
        long nread = 0L;
        byte[] buf = new byte[BUFFER_SIZE];
        int n;
        while ((n = input.read(buf)) > 0) {
            out.write(buf, 0, n);
            nread += n;
            if (nread > 1024 * 1024) {// Exceed 1 MB
                isExceed = true;
                break;
            }
        }
    } catch (IOException ex) {
        throw ex;
    } finally {
        out.close();
        if (isExceed) {// Abort the copy
            Files.deleteIfExists(target);
            throw new IllegalArgumentException();
        }
    }}
  • First question: is there any better solution for it?
  • Second question: my other solution - Before the copy operation, I calculate the size of this InputStream. So I copy the InputStream to ByteArrayOutputStream then get size(). But the problem is InputStream may not markSupported(), so the InputStream cannot be reused in a copy file operation.
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

My personal choice is an InputStream wrapper that counts bytes as it reads them:

public class LimitedSizeInputStream extends InputStream {

    private final InputStream original;
    private final long maxSize;
    private long total;

    public LimitedSizeInputStream(InputStream original, long maxSize) {
        this.original = original;
        this.maxSize = maxSize;
    }

    @Override
    public int read() throws IOException {
        int i = original.read();
        if (i>=0) incrementCounter(1);
        return i;
    }

    @Override
    public int read(byte b[]) throws IOException {
        return read(b, 0, b.length);
    }

    @Override
    public int read(byte b[], int off, int len) throws IOException {
        int i = original.read(b, off, len);
        if (i>=0) incrementCounter(i);
        return i;
    }

    private void incrementCounter(int size) throws IOException {
        total += size;
        if (total>maxSize) throw new IOException("InputStream exceeded maximum size in bytes.");
    }

}

I like this approach because it is transparent, it is re-usable with all input streams and it works well with other libraries. For example copying files up to 4KB with Apache Commons:

InputStream in = new LimitedSizeInputStream(new FileInputStream("from.txt"), 4096);
OutputStream out = new FileOutputStream("to.txt");
IOUtils.copy(in, out);

PS: The main difference of the implementation above with BoundedInputStream is that BoundedInputStream does not throw an exception when the limit is exceeded (it just closes the stream)


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...