复制输入流,如果大小超过限制,则中止操作

2022-09-02 09:02:14

我尝试将 InputStream 复制到文件,如果 InputStream 的大小大于 1MB,则中止该副本。在Java7中,我编写了如下代码:

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();
        }
    }}
  • 第一个问题:有没有更好的解决方案?
  • 第二个问题:我的另一个解决方案 - 在复制操作之前,我计算这个输入流的大小。因此,我复制输入流,然后获得.但问题是 InputStream 可能不会,所以 InputStream 不能在复制文件操作中重用。ByteArrayOutputStreamsize()markSupported()

答案 1

我个人选择的是一个 InputStream 包装器,它在读取字节时对字节进行计数:

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.");
    }

}

我喜欢这种方法,因为它是透明的,它可以在所有输入流中重复使用,并且可以与其他库很好地配合使用。例如,使用Apache Commons复制最大4KB的文件:

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

PS:上面与BoundedInputStream实现的主要区别在于,BoundedInputStream在超过限制时不会引发异常(它只是关闭流)


答案 2

有以下现成的解决方案:


推荐