复制InputStream,如果大小超过限制,则中止操作[英] Copy InputStream, abort operation if size exceeds limit

问题描述

我尝试将输入流将其复制到文件,如果输入流的大小大于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复制到ByteArrayOutputStream,然后获取size().但是问题是InputStream可能不会markSupported(),因此不能在复制文件操作中重复使用InputStream.

推荐答案

第一个问题:有什么更好的解决方案吗?

不是真的.当然,不是要好得多.

第二个问题:我的其他解决方案 - 在复制操作之前,我计算输入流的大小.因此,我将InputStream复制到bytearrayoutputstream,然后获取size().但是问题是InputStream可能无法标记为(),因此不能在复制文件操作中重复使用输入流.

撇开上述语句而不是问题...

如果将字节复制到ByteArrayOutputStream,则可以从baos.toByteArray()返回的字节数组中创建ByteArrayInputStream.因此,您无需标记/重置原始流.

但是,这是实施此功能的一种非常丑陋的方式.尤其是因为您正在阅读和缓冲无论如何输入流.

其他推荐答案

我的个人选择是一个输入流包装器,它在读取它们时计算字节:

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不会抛出异常(它仅关闭流)

其他推荐答案

有以下准备解决方案:

本文地址:https://www.itbaoku.cn/post/978797.html