繁体   English   中英

Java:如何计算从 InputStream 读取的字节数而不分配之前的全部内存

[英]Java: How to count read bytes from InputStream without allocating the full memory before

我有一个 Java 后端,用户可以在其中上传文件。 我想将这些上传的文件限制为最大大小,并希望在上传发生时检查上传的字节数,并在达到限制后立即中断传输。

目前我在分配之前使用 InputStream.available() 来确定估计大小,但这似乎被视为不可靠。

有什么建议吗?

当您想知道读取了多少字节时,您可以使用Guava 的 CountingInputstreamApache IO 的 CountingInputStream

另一方面,当您想在达到某个限制时立即停止上传时,只需在读取字节块时进行计数,并在超过限制时关闭流。

int count = 1;
InputStream stream;
if (stream.available() < 3) {
count++;
}
Result:
[0][1]{2][3] 
 1  1  1  1

您不必“之前分配[e] 全部内存”。 只需使用一个正常大小的缓冲区,比如 8k,并执行正常的复制循环,计算传输的总数。 如果超过配额,则停止并销毁输出文件。

如果您使用 servlet 和多部分请求,您可以这样做:

public void doPost( final HttpServletRequest request, final HttpServletResponse response )
    throws ServletException, IOException {
  String contentLength = request.getHeader("Content-Length");
  if (contentLength != null && maxRequestSize > 0 && 
           Integer.parseInt(contentLength) > maxRequestSize) {
     throw new MyFileUploadException("Multipart request is larger than allowed size");
  }
}

我的解决方案如下所示:

public static final byte[] readBytes (InputStream in, int maxBytes)
throws IOException {
    byte[] result               = new byte[maxBytes];
    int bytesRead               = in.read (result);
    if (bytesRead > maxBytes) {         
        throw new IOException   ("Reached max bytes (" + maxBytes + ")");
    }       
    if (bytesRead < 0) {            
        result                  = new byte[0];
    }
    else {
        byte[] tmp              = new byte[bytesRead];
        System.arraycopy        (result, 0, tmp, 0, bytesRead);
        result                  = tmp;
    }       
    return result;
}

编辑:新变种

public static final byte[] readBytes (InputStream in, int bufferSize, int maxBytes)
throws IOException {

    ByteArrayOutputStream out       = new ByteArrayOutputStream();
    byte[] buffer                   = new byte[bufferSize];

    int bytesRead                   = in.read (buffer);
    out.write                       (buffer, 0, bytesRead);

    while (bytesRead >= 0) {

        if (maxBytes > 0 && out.size() > maxBytes) {

            String message          = "Reached max bytes (" + maxBytes + ")";
            log.trace               (message);
            throw new IOException   (message);
        }

        bytesRead                   = in.read (buffer);

        if (bytesRead < 0)
            break;

        out.write                   (buffer, 0, bytesRead);
    }

    return out.toByteArray();
}

read 的所有方法实现都返回读取的字节数。 因此,您可以启动一个计数器并在每次读取时适当地增加它,以查看到目前为止您已读取了多少字节。 方法 available() 允许您查看此时缓冲区中有多少字节可供读取,它与文件的总大小无关。 这种方法对于优化您的阅读非常有用,因此每次您都可以请求读取随时可用的块并避免阻塞。 同样在您的情况下,您可以在阅读之前预测下一次阅读后您将拥有的字节数是否会超过您的限制,因此您甚至可以在阅读下一个块之前取消它

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM