Am I closing my input stream correctly in Java?

别等时光非礼了梦想. 提交于 2020-05-24 04:14:29

问题


I created a class that extends InputStream so that I can keep count of the number of bytes being read and throw an exception if it exceeds a max limit that I define.

Here is my class:

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

This is coming from: Copy InputStream, abort operation if size exceeds limit, I am implementing a Jersey API that needs to fail if a user is uploading a file that is too large.

Here is my resource class:

    @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 stream = new LimitedSizeInputStream(
           file.getValueAs(InputStream.class), MAX_FILE_SIZE_IN_BYTES))
        {
            // some logic
        }
      catch (IOException e)
        {
            // handle failure
        }
}

I wrapped LimitedSizeInputStream in my try resource so I think the stream should close properly. I'm just a bit confused as to whether the close is handled correctly or if I'm technically opening two input streams through LimitedSizeInputStream and file.getValueAs(InputStream.class) and only one is closing?


回答1:


The try-with-resources only closes the declared resource. So will only close metadataStream.

You should implement the close method in LimitedSizeInputStream to close the original stream.

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



回答2:


If LimitedSizeInputStream extends InputStream and wraps another stream, then @areus's solution is the best one.

An alternative approach would be to extend FilterInputStream, like this:

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.
}

Note that FilterInputStream provides default implementations of the API methods that may prove useful.

The javadoc provides details of what the default method implementations do.



来源:https://stackoverflow.com/questions/61738574/am-i-closing-my-input-stream-correctly-in-java

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!