我用Java正确关闭输入流了吗?

问题描述 投票:1回答:2

我创建了一个扩展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.");
            }
        }
    }

这来自:Copy InputStream, abort operation if size exceeds limit,我正在实现一个Jersey API,如果用户上传的文件太大,该API将会失败。

这是我的资源分类:

    @POST
    @Consumes(MediaType.MULTIPART_FORM_DATA)
    @Path("/test")
    public Response load(
        @Context HttpServletRequest request,
        @FormDataParam(FILE_FIELD) FormDataBodyPart file)
    {
      if (request.getContentLength() > MAX_FILE_SIZE_IN_BYTES)
        {
            // fail fast handle failure
        }

      try (InputStream metadataStream = new LimitedSizeInputStream(
           file.getValueAs(InputStream.class), MAX_FILE_SIZE_IN_BYTES))
        {
            // some logic
        }
      catch (IOException e)
        {
            // handle failure
        }
}

我在我的try资源中包装了LimitedSizeInputStream,所以我认为流应该正确关闭。我对是否正确处理关闭操作感到困惑,或者我是否正在通过LimitedSizeInputStream和file.getValueAs(InputStream.class)打开两个输入流,并且只有一个正在关闭?

java jersey inputstream dropwizard
2个回答
2
投票

try-with-resources仅关闭声明的资源。因此只会关闭metadataStream

您应该在close中实现LimitedSizeInputStream方法以关闭原始流。

@Override
public void close() throws IOException {
    original.close();
}

0
投票

如果LimitedSizeInputStream扩展了InputStream并包装了另一个流,那么@areus的解决方案是最好的解决方案。

一种替代方法是扩展FilterInputStream,如下所示:

public class LimitedSizeInputStream extends FilterInputStream
{
    private final long maxSize;
    private long total;

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

    // use 'this.in' instead of 'this.original'
    // at least one of the 'read' methods needs to be overridden.
}

请注意,FilterInputStream提供了可能证明有用的API方法的默认实现。

javadoc提供了默认方法实现的详细信息。

© www.soinside.com 2019 - 2024. All rights reserved.