Рядом с предыдущей статьей мы будем продолжать изучать байтовые потоковые операции в Java.
Декоратор буферированный потоковой буферист/outputstream
Поток декоратора на самом деле представляет собой поток ввода -вывода файла, основанный на дизайне «режим декоратора», а наш буферный поток - только один из них. Давайте посмотрим.
Перед этим мы использовали файловые чтения и записи потоков FileInputStream и FileOutputStream как чтение, так и записи из байта диска или байта, что очень много времени.
Наш буферный поток может предварительно прочитать количество байтов указанной емкости с диска в одно время в память, а последующие операции чтения будут считываться непосредственно из памяти для повышения эффективности. Давайте посмотрим на конкретную реализацию буферированных потоков:
Давайте сначала возьмем BufferedInputStream в качестве примера, давайте кратко упомянем ее основные свойства:
BUF - это байт -массив, используемый для буферизации чтения. Его значение будет заполняться непрерывно при чтении потока, и последующие операции чтения могут быть напрямую на основе этого буферированного массива.
Default_buffer_size Указывает размер буфера по умолчанию, то есть длина массива BUF. Max_buffer_size указывает верхний предел буфера.
Граф указывает на последний допустимый индекс байтов в буферированном массиве. POS указывает на следующую позицию индекса байтов, которая будет прочитана.
Markpos и Marklimit используются для повторения операций чтения.
Далее, давайте посмотрим на несколько примеров конструкторов BufferedInputStream:
public BufferedInputStream (inputStream in) {this (in, default_buffer_size);} public BufferedInputStream (inputStream In, int size) {super (in); if (size <= 0) {бросить новый allosalargumentException ("Размер буфера <= 0"); } buf = new Byte [size];}В целом, первое должно пройти только в экземпляре InputStream, который «украшен» и использовать буфер размера по умолчанию. Последний может явно указывать размер буфера.
Кроме того, Super (In) сохраняет этот экземпляр InputStream в поле in -атрибута родительского класса FilterinPutStream, и все фактические операции считывания дисков выдаются этим экземпляром InputStream.
Давайте посмотрим на наиболее важные операции чтения и то, как заполнен буфер.
public synchrinized int read () бросает ioException {if (pos> = count) {fill (); if (pos> = count) return -1; } return getBufifoPen () [pos ++] & 0xff;}Я считаю, что все уже знакомы с этим методом. Он считывает следующий байт из потока и возвращает его, но реализация в деталях все еще немного отличается.
Граф указывает на следующую позицию достоверного индекса байта в буферированном массиве, и POS указывает на следующую позицию индекса байта, который будет прочитан. Теоретически, POS не может быть больше, чем считаться, не более равных.
Если POS равен подсчету, это означает, что все достоверные байты в массиве буферов были прочитаны. В настоящее время необходимо отказаться от «бесполезных» данных в буфере, а партия новых данных перезагружается от диска для заполнения буфера.
На самом деле, метод заполнения - это то, что он делает. У него много кода, поэтому я не буду брать вас, чтобы проанализировать его. Если вы понимаете его функцию, это, вероятно, легко проанализировать ее реализацию.
Если POS по -прежнему равен подсчету после вызова метода заполнения, это означает, что экземпляр InputStream не считывает никаких данных из потока, то есть в потоке файлов нет данных для чтения. Для этого см. Строку 246 метода заполнения.
В общем, если буфер успешно заполнен, наш метод чтения займет байт непосредственно из буфера и вернет его в абонента.
Общедоступный синхронизированный int read (byte b [], int off, int len) {// .....}Этот метод также является «знакомым», больше не имеет ненужного объяснения, реализация аналогична.
Метод пропуска используется для пропуску количества байтов указанной длины для продолжения чтения потока файла:
Публичный синхронизированный длинный Skip (long n) {// ......}Следует отметить, что метод Skip пытается пропустить n байтов, но он не гарантированно пропустит n байтов. Метод возвращает фактическое количество пропущенных байтов. Если оставшееся количество доступных байтов в буферном массиве меньше N, фактическое количество байтов, которые можно пропустить в буферированном массиве, в конечном итоге будет пропущено.
Наконец, давайте поговорим об этом близком методе:
public void cloid () бросает ioException {byte [] buffer; while (((buffer = buf)! = null) {if (bufupdater.compareanddset (это, buffer, null)) {inputstream input = in; in = null; if (input! = null) input.close (); возвращаться; } // else повторение в случае, если новый BUF был оборван в fill ()}}Метод закрытия опустошит «украшенный» поток и вызовет его близкий метод для выпуска соответствующих ресурсов, который в конечном итоге очистит пространство памяти, занятое массивом буфера.
BufferedInputStream предоставляет возможности буферизации чтения, в то время как BufferedOutputStream предоставляет возможности буферизации записи, то есть операции записи памяти не будут немедленно обновлены на диск и будут временно сохранены в буфере и будут записаны вместе, когда буфер будет заполнен.
Защищенный байт BUF []; Защищенный int count;
BUF представляет внутренний буфер, а количество представляет фактическую способность данных в буфере, то есть количество эффективных байтов в BUF, а не длину массива BUF.
public BufferedOutputStream (outputStream Out) {this (out, 8192);} public BufferedOutputStream (outputStream Out, int size) {super (out); if (size <= 0) {бросить новый allosalargumentException ("Размер буфера <= 0"); } buf = new Byte [size];}С той же идеей реализации необходимо предоставить экземпляр выходного потока выходного потока, и размер буфера также можно указать.
публичная синхронизированная void write (int b) бросает ioException {if (count> = buf.length) {flushbuffer (); } buf [count ++] = (byte) b;}Метод записи сначала проверит, может ли буфер все еще вместить эту операцию записи. Если операция записи диска не может быть инициирована, все данные буфера будут записаны в файл диска, в противном случае буфер будет записан в буфер сначала.
Конечно, BufferedOutputStream также предоставляет метод промывки для обеспечения интерфейса снаружи, то есть вам не нужно ждать, пока буфер будет заполнен, прежде чем записывать данные на диск. Вы также можете явно вызвать этот метод, чтобы очистить буфер и обновить файлы дисков.
public Synchrinized void flush () бросает ioException {flushbuffer (); out.flush ();}Что касается буферированных потоков, основной контент вводится, как указано выше. Это поток, который может значительно повысить эффективность. Благодаря этому количество доступа дисков может быть уменьшено, а эффективность выполнения программы может быть улучшена.
Мы не будем обсуждать поток сериализации объекта объект ObjectIntput/outputStream и потока декоратора DataInput/outputStream на основе основных типов. Когда мы изучаем сериализацию, мы снова обсудим эти два байтовых потока.
Все коды, изображения и файлы в статье хранятся в облаке на моем GitHub:
(https://github.com/singleyam/overview_java)
Вы также можете загрузить локально.
Суммировать
Вышеуказанное - все содержание этой статьи. Я надеюсь, что содержание этой статьи имеет определенную справочную ценность для каждого обучения или работы. Если у вас есть какие -либо вопросы, вы можете оставить сообщение для общения. Спасибо за поддержку Wulin.com.