1) Как буферизованные потоки работают в фоновом режиме, как они отличаются от обычных потоков и каковы преимущества их использования?
2) DataInputStream
также байт. Но он имеет методы для readLine()
. Какой смысл здесь?
1) Как буферизованные потоки работают в фоновом режиме, как они отличаются от обычных потоков и каковы преимущества их использования?
2) DataInputStream
также байт. Но он имеет методы для readLine()
. Какой смысл здесь?
Из BufferedInputStream javadoc:
BufferedInputStream добавляет функции к другому входному потоку, а именно: возможность буферизации ввода и поддержки меток и методов reset. Когда BufferedInputStream создается, создается внутренний буферный массив. Поскольку байты из потока считываются или пропускаются, внутренний буфер пополняется по мере необходимости из содержащегося входного потока, по одному байту за один раз. Операция метки запоминает точку во входном потоке, а операция reset приводит к тому, что все прочитанные байты, поскольку самая последняя операция метки должна быть перечитана до того, как новые байты будут взяты из содержащегося входного потока.
Внутри используется буферный массив, и вместо того, чтобы считывать байты отдельно от базового входного потока, достаточное количество байтов считывается для заполнения буфера. Как правило, это приводит к более высокой производительности, так как в базовом потоке ввода требуется меньше чтений.
В противном случае значение true для BufferedOutputStream.
mark() и reset() можно использовать следующим образом:
1 BufferedInputStream bis = new BufferedInputStream(is);
2 byte[] b = new byte[4];
3 bis.read(b); // read 4 bytes into b
4 bis.mark(10); // mark the stream at the current position - we can read 10 bytes before the mark point becomes invalid
5 bis.read(b); // read another 4 bytes into b
6 bis.reset(); // resets the position in the stream back to when mark was called
7 bis.read(b); // re-read the same 4 bytes as line 5 into b
Чтобы пояснить mark/ reset еще...
BufferInputStream внутренне запоминает текущую позицию в буфере. Когда вы будете читать байты, позиция будет увеличиваться. Вызов метки (10) сохранит текущую позицию. Последующие вызовы для чтения будут продолжать увеличивать текущую позицию, но вызов reset вернет текущую позицию обратно к ее значению при вызове метки.
Аргумент для отметки указывает, сколько байтов, которые вы можете прочитать после вызова метки перед положением метки, становится недействительным. После того, как позиция метки недействительна, вы можете больше не называть reset, чтобы вернуться к ней.
Например, если метка (2) была использована в строке 4 выше, исключение IOException будет выбрано, если в строке 6 вызывается reset(), поскольку позиция метки была бы недействительной, так как мы читаем более 2 байтов.
Буферизованные читатели/писатели/InputStreams/OutputStreams читают и записывают в ОС в больших кусках для оптимизации. В случае писателей и выходных потоков данные буферизуются в памяти до тех пор, пока не будет достаточно собранных, чтобы выписать большой кусок. В случае считывателей и входных потоков большой фрагмент считывается в виде диска/сети/... в буфер, и все чтения выполняются из этого буфера, пока буфер не будет пустым, и будет прочитан новый фрагмент.
DataInputStream действительно байт. Метод readLine устарел. Внутри он считывает байты с диска/сети/... byte-for-byte, пока не соберет полную строку. Таким образом, этот поток можно ускорить, используя BufferedInputStream в качестве источника, так что байты для строки считываются из буфера внутри памяти, а не непосредственно с диска.
При небуферизованном вводе-выводе каждый запрос на чтение или запись передается непосредственно в операционную систему. Буферизованные потоки ввода-вывода Java считывают и записывают данные в собственный буфер памяти (обычно это массив байтов). Вызовы в операционной системе производятся только тогда, когда буфер пуст (при чтении), или буфер заполнен (при записи). Иногда рекомендуется сбросить буфер вручную после критических точек в вашем приложении.
Так как вызовы API операционной системы могут привести к доступу к диску, активности сети и т.п., это может быть довольно дорогостоящим. Использование буферов для загрузки собственного ввода-вывода операционной системы в более крупные блоки часто значительно повышает производительность.
Буферизованные потоки записывают или читают данные в более крупных фрагментах - буферизация. В зависимости от базового потока это может значительно увеличить производительность.
От java.io.BufferedOutputStream Javadocs:
Установив такой выходной поток, приложение может записывать байты в базовый выходной поток без обязательно вызывает вызов базовая система для каждого байта написано.
Чтобы уменьшить этот накладные расходы, платформа Java реализует буферизованные потоки ввода-вывода. Буферизованные входные потоки считывают данные из области памяти, известной как буфер; API-интерфейс нативного ввода вызывается только тогда, когда буфер пуст. Аналогично, буферизованные выходные потоки записывают данные в буфер, а собственный API вывода вызывается только тогда, когда буфер заполнен.