Здесь есть два вопроса.
<сильный>1. Буферизация
Представьте, что вы живете в миле от ближайшего источника воды и каждый час выпиваете чашку воды. Ну, ты же не будешь ходить за каждой чашкой к воде. Ходите один раз в день и возвращайтесь домой с ведром воды, достаточным для того, чтобы наполнить чашку 24 раза.
Сегмент — это буфер.
Представьте, что в вашу деревню подается вода из реки. Но иногда река пересыхает на месяц; в других случаях река приносит так много воды, что деревня затапливается. Итак, вы строите плотину, а за плотиной находится водохранилище. Водохранилище наполняется в сезон дождей и постепенно опорожняется в сухой сезон. Деревня получает стабильный поток воды круглый год.
Резервуар представляет собой буфер.
Потоки данных в вычислениях аналогичны обоим этим сценариям. Например, вы можете получить несколько килобайт данных из файловой системы за один системный вызов ОС, но если вы хотите обрабатывать по одному символу за раз, вам нужно что-то похожее на резервуар.
BufferedReader содержит в себе другой Reader (например, FileReader), который является рекой, и массив байтов, который является резервуаром. Каждый раз, когда вы читаете из него, он делает что-то вроде:
if there are not enough bytes in the "reservoir" to fulfil this request
top up the "reservoir" by reading from the underlying Reader
endif
return some bytes from the "reservoir".
Однако когда вы используете BufferedReader, вам не нужно знать, как он работает, достаточно знать, что он работает.
<сильный>2. Подходит для изображений
Важно понимать, что BufferedReader и FileReader являются примерами Readers. Возможно, вы еще не изучали полиморфизм в своем обучении программированию, поэтому, когда вы это сделаете, помните об этом. Это означает, что если у вас есть код, который использует FileReader
, но только те его аспекты, которые соответствуют Reader
, то вы можете заменить его на BufferedReader
, и он будет работать точно так же.
Это хорошая привычка объявлять переменные как наиболее общий класс, который работает:
Reader reader = new FileReader(file);
... потому что тогда это будет единственное изменение, которое вам нужно для добавления буферизации:
Reader reader = new BufferedReader(new FileReader(file));
Я пошел по этому пути, потому что все Reader
меньше подходят для изображений.
Reader
имеет два метода read
:
int read(); // returns one character, cast to an int
int read(char[] block); // reads into block, returns how many chars it read
Вторая форма не подходит для изображений, потому что она определенно читает символы, а не целые числа.
Первая форма выглядит так, как будто все в порядке — в конце концов, она читает целые числа. И действительно, если вы просто используете FileReader, это вполне может сработать.
Однако подумайте о том, как будет работать BufferedReader, обернутый вокруг FileReader. При первом вызове BufferedReader.read() он вызовет FileReader.read(buffer) для заполнения своего буфера. Затем он вернет первый char
буфера обратно в int и вернет его.
Особенно, когда вы добавляете в картину многобайтовые кодировки, это может вызвать проблемы.
Поэтому, если вы хотите читать целые числа, используйте InputStream
, а не Reader
. InputStream
имеет int read(byte[] buf, int offset, int length)
-- байты гораздо надежнее возвращаются из int и обратно, чем chars.
person
slim
schedule
06.03.2014