2016-02-19 5 views
0

У меня есть InputStream от ProcessBuilder, который аккуратно читает поток stdout.Как получить размер InputStream?

Вопрос: как я могу узнать размер этого inmemory InputStream, так что я могу написать его в http: 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()); 
+4

Вы не узнаете, пока не прочтете все. Выход может быть бесконечным. –

+0

Вам лучше вернуть это как поток в браузер. –

+0

См. Этот ответ: http://stackoverflow.com/questions/11746978/java-inputstream-size –

ответ

4

Нет такой величины, как размер входного потока. Рассмотрите программу, которая никогда не выходит, или сокет, который никогда не прекращает отправку. И вам не нужно знать, чтобы записать его в заголовок HttpResponse. Управление Content-length осуществляется автоматически.

+0

@BalusC Лучше использовать временный файл, почему? – EJP

+0

@BalusC «Память дружественная» как?Согласно вашему комментарию, использование памяти не превышает «буфер». Использование временного файла только добавляет латентность: он действительно не сохраняет память. – EJP

+0

@BalusC Вы не ответили на мой вопрос. – EJP

2

Если вы действительно хотите установить содержимое заголовка, вы должны прочитать весь поток перед записью в OutputStream ответа

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()); 

Примечание: При таком подходе вы сейчас читаете весь поток в памяти это повлияет на доступную память и, вероятно, не будет хорошо масштабироваться.

+0

Все это бессмысленно, так как Java уже управляет контентом для вас. – EJP

+1

ха? нет? Заголовки (включая длину контента) отправляются перед записью в выходной поток. Если вы пишете один байт в выходной поток, вы не можете установить заголовок в этой точке. Таким образом, поток будет отправлен без заголовка длины содержимого, что означает, что клиент НЕ может отображать процент в полном объеме, пока поток получен –

+0

Да, да. Попробуйте это время, как и 20 лет назад, и снова в прошлом месяце. – EJP

1

Попробуйте

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()); 
+0

Никогда не нужно устанавливать длину контента в Java JDK, а использование ByteArrayOutputStream здесь просто пустая трата времени и пространства. И не отвечает на вопрос. – EJP

1

InputStream по своей сути не имеет размера. Вероятно, он может продолжать доставлять байты навсегда. Или производственный конец может остановить поток без предупреждения.

Если вам нужно узнать длину, вы должны прочитать ее до конца, подсчитывать байты и сообщать длину, когда закончите.

Вы беспокоитесь об заголовке HTTP Content-length, и у вас есть точка. Дело в том, что исходная версия HTTP не была разработана для большого, динамически созданного контента. Протокол по своей сути ожидает, что вы узнаете размер содержимого, прежде чем начинать его писать, но как это возможно, если это (например) текущий чат или выход видеокамеры?

Решение: chunked transfer encoding. Здесь вы не устанавливаете заголовок. Вы устанавливаете Transfer-Encoding: chunked, затем записываете содержимое в виде кусков, каждый из которых имеет заголовок размера.

У HTTP RFC есть детали, это или нет, или https://en.wikipedia.org/wiki/Chunked_transfer_encoding немного более дружелюбны.

Однако большинство HTTP API скрывают эту деталь от вас. Если вы не разрабатываете веб-библиотеку с нуля (возможно, по академическим причинам), вам не нужно думать о Content-Length или Transfer-Encoding.

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