В общем виде все решения выглядят так. Заводится буфер – массив символов. Поток направляется в этот буфер. По заполнению данные из массива присоединяются в хвост строки-результата.
Простой способ – использовать трюк со сканером. Вообще класс
Scanner
читает из потока подстроки, разделенные указанным символом. Когда нужно прочитать всю строку сразу, в качестве разделителя устанавливается "\\A"
– спецсимвол «начало строки». Это решение просто в реализации, но имеет проблемы. Размер внутреннего буфера фиксирован (1024 символа), а логика поиска разделителя плохо влияет на производительность.Хорошее решение для продакшна – читать в собственный массив-буфер непосредственно методом
InputStream.read
, либо обернув поток в InputStreamReader
. Данные из буфера затем переправляются в строку через StringBuilder или ByteArrayOutputStream
. За готовой реализацией можно обратиться в библиотеки Apache Commons IO и Google Guava. Полный код реализации и сравнение производительности описаны на stackoverflow.На интервью этот вопрос часто возникает как часть практической задачи, для консольного ввода-вывода. Поэтому, если вы идете на собеседование со своим компьютером, и неуверенно владеете классами работы с потоками, стоит заранее подготовить шпаргалку с кодом.