Длина содержимого выходного потока ответа?

Я пишу в выходной поток различными способами. Как я могу, прежде чем закрыть его, узнать длину содержимого выходного потока?


person Trick    schedule 18.11.2009    source источник


Ответы (3)


Самый простой способ, вероятно, состоит в том, чтобы обернуть его в другую реализацию OutputStream, которая перенаправляет все запросы на запись, но сохраняет внутренний счетчик. Тогда вы просто пишете об этом вместо этого. Не должно быть слишком сложно реализовать - и действительно, он уже может быть.

РЕДАКТИРОВАТЬ: Простое угадывание разумного имени (CountingOutputStream) привело к реализации в Apache Commons IO.

РЕДАКТИРОВАТЬ: Как отмечалось в другом месте, если это для HTTP, и ваш клиент еще не выполняет буферизацию полных данных (в этом случае я бы подумал, что это может определить длину содержимого), вы могут возникнуть проблемы из-за необходимости записи длины перед записью данных. В некоторых случаях вы можете обнаружить, что он будет работать до определенного размера (который буферизирует клиент), а затем выйдет из строя. В таком случае решения Дэвида будут уместны.

person Jon Skeet    schedule 18.11.2009
comment
У, Апачи Коммонс! Я должен начать, не забывая об Apache Commons!!! Я попробую. - person Trick; 18.11.2009
comment
Будет ли это работать с большими данными? Вы должны установить заголовок Content-length, прежде чем писать что-либо в outputStream ответа, как заметил Дэвид. - person Andrey Regentov; 06.02.2014
comment
@AndreyRegentov: Это зависит от контекста. Если вывод буферизуется тем, что вы пишете, все в порядке. И мы не обязательно знаем, что это HTTP, хотя это разумная ставка. Я исправлю свой ответ с несколькими мыслями. - person Jon Skeet; 06.02.2014
comment
@JonSkeet полностью согласен с контекстом. Я пришел сюда, погуглив про HTTP, и невольно предположил, что вопрос касается HTTP (ответ, длина контента), хотя в вопросе об этом ничего нет. - person Andrey Regentov; 06.02.2014
comment
@AndreyRegentov: Хотя это кажется весьма вероятным :) В любом случае, немного добавили и проголосовали за ответ Дэвида. - person Jon Skeet; 06.02.2014

Проблема в том, что вы должны установить длину содержимого в заголовке ответа, прежде чем начнете записывать какие-либо данные в выходной поток. Итак, ваши варианты:

  1. Запишите данные в массив byte[] с помощью ByteOutputStream, а затем скопируйте их в выходной поток ответа, когда у вас будет размер данных. Однако, если вы пишете большие файлы, это явно не вариант.
  2. Запишите данные во временный файл, а затем скопируйте их в вывод ответа, как только вы получите размер файла. В зависимости от того, что вы делаете, это может привести к неприемлемому снижению производительности.
  3. В зависимости от того, насколько дорого обходится генерация данных, вы можете сгенерировать их один раз, выбросить, чтобы получить подсчет, а затем сгенерировать снова. Предполагая, что это вряд ли будет реалистичным решением.
  4. Смиритесь с тем, что вы не сможете сообщить длину контента в заголовке ответа.
person David    schedule 18.11.2009

Вы можете рассмотреть возможность записи в свой собственный ByteArrayOutputStream и сбросить его в поток вывода ответа в самом конце.

person Dmitry    schedule 18.11.2009
comment
Однако это будет очень перегружать память, поскольку каждый байт byte[] съедает один байт памяти JVM. - person BalusC; 18.11.2009