Java 如何获取输入流的大小?

Java 如何获取输入流的大小?,java,inputstream,content-length,Java,Inputstream,Content Length,我有一个ProcessBuilder的InputStream,它可以准确地读取stdout流 问题:如何知道inmemoryInputStream的大小,以便将其写入HttpResponsehttp头 InputStream is = process.getInputStream(); InputStreamReader isr = new InputStreamReader(is); BufferedReader br = new BufferedReader(isr); OutputStr

我有一个
ProcessBuilder
InputStream
,它可以准确地读取
stdout

问题:如何知道inmemory
InputStream
的大小,以便将其写入
HttpResponse
http头

InputStream is = process.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);

OutputStream out = response.getOutputStream();
int bytes;
while ((bytes = br.read()) != -1) {
    out.write(bytes);
}

//how can I know the size of the inmemory stream/file written?
//response.setContentLength((int) pdfFile.length());

输入流的大小是不存在的。考虑一个永不退出的程序,或者一个永不停止发送的套接字节点。您不需要知道如何将其写入
HttpResponse
头。
内容长度
是为您自动管理的。

如果您真的想设置内容长度标题,您需要在写入响应输出流之前读取整个流

ByteArrayOutputStream out = new ByteArrayOutputStream();
byte[] bytes = new byte[1024];
int count;
while ((count = in.read(bytes)) > 0) {
    out.write(bytes, 0, count);
}
response.setContentLength(out.size();
out.writeTo(response.getOutputStream());
注意:使用这种方法,您现在已经将整个流读取到内存中,这将对可用内存产生影响,并且可能无法很好地扩展。

尝试这种方法

    InputStream is = process.getInputStream();
    ByteArrayOutputStream os = new ByteArrayOutputStream();
    int b;
    while ((b = is.read()) != -1)
        os.write(b);
    response.setContentLength(os.size());
    response.getOutputStream().write(os.toByteArray());

InputStream
本身没有大小。可以想象,它可以永远提供字节。或者,生产端可以在没有警告的情况下结束流

如果必须找出长度,则必须读取到最后,计算字节数,并在完成时报告长度

您担心HTTP的
内容长度
头,这是有道理的。事实上,HTTP的原始版本并不是为大型、动态生成的内容而设计的。该协议本质上期望您在开始编写内容之前知道内容的大小——然而,如果是(例如)正在进行的聊天或摄像机的输出,这怎么可能呢

解决方案是HTTP的
分块传输编码
。这里不设置
内容长度
标题。设置
传输编码:chunked
,然后将内容写入块,每个块都有一个大小标题

HTTP RFC对此有详细说明,或者稍微友好一些


然而,大多数HTTP API对您隐藏了这个细节。除非您是从头开始开发web库(可能是出于学术原因),否则您不必考虑
内容长度
传输编码

,直到您阅读完所有内容后才会知道。输出可能是无止境的。您最好将其作为流返回到浏览器。请参阅以下答案:等待;是什么告诉你内容是文本?此外,您甚至没有在读卡器上指定编码(编辑:从注释来看,这似乎不是文本),只是使用固定大小的缓冲区在循环中读写。@BalusC最好使用临时文件为什么?@BalusC“内存友好”如何?根据您的评论,内存使用量没有超过“缓冲区”。使用临时文件只会增加延迟:它不会真正节省内存。@BalusC您还没有回答我的问题。@BalusC但他不需要设置内容长度
HttpResponse
将为他做这件事,必要时也将其分块。@BalusC添加延迟只是为了报告进度不是什么好主意。真正的进度是正在执行的
进程的进度,这对客户端来说是隐藏的。在Java JDK中永远不需要设置内容长度,在这里使用
ByteArrayOutputStream
只是浪费时间和空间。而且没有回答这个问题。@user207421那不是真的。我需要自己处理内容长度,这正是我所需要的。这是毫无意义的,因为Java已经为您管理了内容长度。哈?不,不是吗?头(包括内容长度)在写入outputstream之前发送。如果将单个字节写入outputstream,则无法在该点设置头。因此,流将在没有内容长度头的情况下发送,这意味着客户端无法在接收流时显示完成百分比。嗯,是的,确实如此。试一下,就像我20年前做的那样,上个月又做了一次。完全是胡说八道。Http协议首先是头,然后是响应体。确定您可以写入响应OutputStream而无需设置内容长度头。但如果你设定了它,你就设定了它,这是有好处的。或者你有一个过滤器在为你做这件事?例如gzip filter“如果整个响应都在响应缓冲区内,那么内容长度将自动设置。”我将接受更正
import org.apache.commons.io.IOUtils;

   byte[] bytes = IOUtils.toByteArray(inputStream);
   log.message("bytes .lenght "+bytes.length);

            if (bytes.length > 400000)
//some byte range limit`enter code  can add any byte range
              {
                throw new Exception("File Size is larger than 40 MB ..");
              }