1: BufferedWriter
1. Введение в функции класса:
BufferedWriter, выходной поток символов кэша, его функция заключается в том, чтобы обеспечить функцию кэша для входящего базового потока вывода символов. Точно так же при использовании базового потока вывода символов для записи символов или массивов символов в пункт назначения, соединение с пунктом назначения должно открываться каждый раз, когда он записывается. Такой частый доступ постоянно эффективен, и он также может нанести определенные повреждения среды хранения. Например, когда мы постоянно записываем байты на диск, преувеличено писать очень большую единицу G в указанный файл на диске, и если мы не пишем байт, канал на этот диск должен быть открыт один раз. Этот результат, несомненно, ужасен. , и когда мы используем BufferedWriter, чтобы обернуть базовый выходной поток символов, такой как FileReader, мы можем сначала записать символы, которые будут записаны в файл в программе в встроенное пространство кэша BufferedWriter, а затем, когда определенная сумма будет достигнута, оно будет записано в поток FileReader одновременно. В настоящее время FileReader может открыть канал и написать этот блок данных в файл. Хотя невозможно достичь эффекта записи всех данных на диск в одном доступе, это также значительно повышает эффективность и уменьшает количество доступа к диску! Это его значение. Его конкретный принцип работы здесь кратко упоминается: он может быть довольно запутанным здесь. Вы можете подробно рассмотреть исходный код. Если вы не понимаете, то оглянитесь сюда. Всякий раз, когда вы пишете символ или массив символов в буффич -авторат в программе, вы будете проверять, является ли кэшированный массив символов (размер BUF по умолчанию или указан при создании BW, как правило, используется по умолчанию). Если он не заполнен, персонажи записаны в BUF. Если он заполнен, основной писатель (char [] b, int off, int называется. Len) пишет всех персонажей в BUF в основной за один раз, если массив персонажей написан, если BUF заполнен, так же, как и обработка, когда он заполнен выше, если на письменном массиве можно хранить, чем на списке. Все символы в BUF будут записаны на Out, а затем хранить символы, которые будут записаны в BUF (хранилище из подсказка 0), если персонажи, которые должны быть записаны в Out, превышают длину BUF, то пишите непосредственно на Out,
2. Введение в API BufferedWriter:
A: Ключевое слово частный писатель; Нижний выходной выходной поток Private Char CB []; Buffer Array Private Int Nchars, NextChar; NCHARS-размер размера NCHARS, NextChr-Subscript следующего символа в CB Private Static Int DefaultChuffersize = 8192; По умолчанию CB Size Private String LineParator; Новый персонаж, используемый для метода Newline. Разные платформы имеют разные значения. B: Метод Construct BufferedWriter (Writer Out) Создает BufferedWriter BW, используя размер CB по умолчанию. BufferedWriter (Writer Out, Int SZ) создает BufferedWriter BW, используя размер CB по умолчанию. C: Общий метод void Cloud () закрывает этот поток и выпускает ресурсы, связанные с этим потоком. void flushbuffer () промыл кэшированные символы в CB в базовый, void flush () обновляет этот поток и обновляет базовый поток void void newline (). void write (int c) записывает одного персонажа в CB. void write (char cbuf [], int off, int len). Напишите длину символа LEN из индекса с помощью CB void write (String s, int off, int len) Напишите часть строки в CB
3. Анализ исходного кода
пакет com.chy.io.original.code; импорт java.io.ioexception; импорт java.io.printwriter;/*** Предоставьте функцию буферизации для потоков вывода символов и повысить эффективность. Вы можете использовать указанный символ для буферизации размера массива или символа по умолчанию для буферизации размера массива. */public Class BufferedWriter Extends writer {// Base Array Private Writer Out; // буферизация массива частной char cb []; // nchars-общее количество символов в CB, NextChar-The Intecript следующего символа в CB Private Int Nchars, Nextchar; // по умолчанию CB Size Private Static Int DefaultChuffersize = 8192; /*** Строка сепаратора линии. Это значение свойства Line.sparator * в тот момент, когда поток был создан. * Линия Newline символ, используемый для метода Newline. Разные платформы имеют разные значения. */ private String LineParator; /*** Создать BufferedWriter BW с размером CB по умолчанию. */ public BufferedWriter (writer Out) {this (out, defaultChuffersize); } / ** * Создать Br и инициализировать связанные поля с указанным размером CB * / public BufferedWriter (writer Out, int sz) {super (out); if (sz <= 0) бросить новый allosalargumentException ("размер буфера <= 0"); this.out = out; cb = new char [sz]; nchars = sz; nextchar = 0; // Получить представление символов Newline на разных платформах. lineParator = (string) java.security.accesscontroller.doprivileged (new sun.security.action.getPropertyAction ("line.separator")); } / ** Объяснить, закрыт ли базовый выходной поток символов. } /*** Снимите кэшированные символы в CB в основном, но не промывают символы в основном. * И очистить CB. */ void flushbuffer () бросает ioException {synchronized (lock) {recaiveOpen (); if (nextchar == 0) return; out.write (cb, 0, nextchar); NextChardChar = 0;}} /*** Напишите один символ в CB. */ public void write (int c) бросает ioException {synchronized (lock) {recaiveOpen (); if (nextchar> = nchars) flushbuffer (); CB [nextChar ++] = (char) c;}} /** * наш собственный небольшой метод MIN, чтобы избежать загрузки java.lang.math, если мы запустили * из дескрипторов файлов, и мы пытаемся распечатать трассировку стека. */ private int min (int a, int b) {if (a <b) return a; return b; } / *** Напишите длину символа LEN из индекса в CB* / public void write (char cbuf [], int off, int len), выбросит ioexception {synchronized (lock) {recaveopen (); if ((off <0) || (off> cbuf.length) || (len <0) || ((off + len)> cbuf.length) || ((off + len) <0)) {бросить новый indexoutofboundsexception (); } else if (len == 0) {return; } if (len> = nchars) {/* Если Len больше, чем длину CB, то существующие символы в CB и символы в CBUF прямо записаны, вместо того, чтобы писать в CB, а затем писать. */flushbuffer (); out.write (cbuf, off, len); return; } int b = off, t = off + len; while (b <t) {int d = min (nchars - nextchar, t - b); system.arraycopy (cbuf, b, cb, nextchar, d); b += d; nextchar += d; if (nextchar> = nchars) flushbuffer (); }}} / *** Напишите часть строки в Cb* / public void write (string s, int off, int len) throws ioException {synchronized (lock) {useopen (); int b = off, t = off + len; while (b <t) {int d = min (nchars - nextchar, t - b); s.getchars (b, b +d, cb, nextchar); b += d; nextchar += d; if (nextchar> = nchars) flushbuffer (); }}} /*** Напишите новую линию. */ public void newline () бросает ioException {write (lineparator); } / *** Обновить этот поток и обновить базовый поток одновременно* / public void flush () бросает ioException {synchronized (lock) {flushbuffer (); out.flush ();}} /*** Закройте этот поток и выпустите ресурсы, связанные с этим потоком. */ public void close () бросает ioException {synchronized (lock) {if (out == null) {return; } try {flushBuffer (); } наконец {out.close (); out = null; cb = null; }}}}4. Пример демонстрации: используйте следующий BufferedReader для реализации копирования файлов типа символа.
Два: BufferedReader
1. Введение в функции класса:
Буференный входной поток символов, его функция состоит в том, чтобы обеспечить функцию буферизации для входящего базового потока ввода символов. Он будет читать символы в базовом потоке ввода символов (In) в свой собственный буфер (встроенный кэшированный массив символов), а затем программа вызывает метод чтения BufferedReader, чтобы прочитать символы в буфере в программу. Когда символы в буфере прочитаны, BufferedReader будет читать следующий блок данных из In in и в буфер для чтения программы до тех пор, пока данные IN IN IT It It It. Преимущества этого, во -первых, это повышают эффективность чтения, а во -вторых, это уменьшает количество соединений, чтобы открыть среду хранения. По подробным причинам, BufferedWriter, упомянутый ниже. Существует ключевой метод Fill (), который должен заполнить данные из In in и заполнять данные из буфера каждый раз, когда данные в буфере читаются в десять раз быстрее, чем то, что читается с диска! Это очень ужасающее улучшение эффективности. В то же время мы не можем указать размер буфера BufferedReader без запрета. В конце концов, для чтения займет много времени, чтобы читать один раз. Во -вторых, цена памяти относительно дорогая. Что мы можем сделать, так это попытаться найти в нем разумные моменты. Как правило, нам не нужно беспокоиться об этом и использовать размер буфера по умолчанию при создании буферизации.
2. Введение в API BufferedReader:
A: Построение метода BufferedReader (Reader in, int sz) создает буферизатор на основе указанного размера и базового потока ввода символов. BraferedReader (чтения) Используйте размер по умолчанию для создания буферизованного потока базового выходного потока B: Общий метод void Cloid () закрыть этот поток и освободить все ресурсы, связанные с этим потоком void Mark (int ReadaHeadlImit). Определите позицию этого потока в этом времени. может читать символы int Read () считывает один символ и возвращает в целочисленной форме. Если конец in прочитал, он возвращает -1. int Read (char [] cbuf, int off, int len) Читать символы LEN в CBUF, начиная от подписка, длина Len String Line () Прочитайте линию Long Skip (Long N) Discard N символов в CBUF
3. Анализ исходного кода
пакет com.chy.io.original.code; import java.io.ioexception;/*** Добавить массив CB Bufficer для базового ввода символов. Повышение эффективности * @version 1.1, 13/11/17 * @authorandychen */public class bufferedreater extends reader {private Reader in; Частный Char CB []; Private Int Nchars, NextChar; Частный статический финал Int Invalidated = -2; Частный статический финал int unmarded = -1; private int markedchar = unmarded; private int readaheadlimit = 0; /*Действительно только при Markedchar> 0*// ** Если следующий символ является линейным каналом, пропустите его*/ private boolean skiplf = false; / ** Флаг Skiplf, когда отметка была установлена*/ private boolean markedskiplf = false; Private Static Int DefaultChuffersize = 8192; Частный статический int delaultexpectedlinelength = 80; /*** Создайте буферный читатель на основе указанного размера и базового потока ввода символов. Br */ public BufferedReader (Reader in, int sz) {super (in); if (sz <= 0) бросить новый allosalargumentException ("Размер буфера <= 0"); this.in = in; cb = new char [sz]; nextchar = nchars = 0; } / *** Используйте размер по умолчанию, чтобы создать буферизованный поток базового выходного потока* / public BufferedReader (Reader In) {this (in, defaultChuffersize); } / ** Обнаружение того, является ли базовый поток ввода символов в закрытии* / private void gativeopen () бросает ioException {if (in == null) бросить новое ioException («Поток закрыт»); } /*** Заполните CB. */ private void fill () бросает ioException {int dst; if (markedchar <= unmarked) {/ *no mark */ dst = 0;} else {/ *marked */ int delta = nextchar - markedchar; if (delta> = readaHeadlimit) {/ * Прошел мимо предела чтения-недействительный Марк */MarkedChar = Invalidated; readaHeadlimit = 0; dst = 0; } else {if (readaHeadlimit <= cb.length) { / * Shuffle в текущем буфере * / System.ArrayCopy (CB, MarkedChar, CB, 0, Delta); markedchar = 0; dst = delta;} else { / * buffer перераспределять для размещения предела чтения-char ncb [] = new char [readaheadlimit]; System.ArrayCopy (CB, MarkedChar, NCB, 0, Delta); cb = ncb; markedchar = 0; dst = delta;} nextChar = nchars = delta; }} int n; do {n = in.read (cb, dst, cb.length - dst);} while (n == 0); if (n> 0) {nchars = dst + n; nextChardCher = dst;}} /*** Прочитайте один символ и возвращайте как целое число. Если конец in прочитал, он возвращает -1. */ public int read () бросает ioException {synchronized (lock) {recaiveOpen (); for (;;) {if (nextchar> = nchars) {fill (); if (nextchar> = nchars) return -1;} if (skiplf) {skiplf = false; if (cb [nextchar] == '/n') {nextchar ++; продолжить; }} вернуть cb [nextChar ++]; }}} /*** Читать символы LEN в CBUF из LEN LEN LEN, начиная с подписки* /private int read1 (char [] cbuf, int off, int len), бросает ioException {if (nextchar> = nchars) { /* Если запрошенная длина, по крайней мере, такая же большая, как и не опустить, и если не опускает, и если не опускает, и если не опускает, и если не опустить, и если не опустить. персонажи в локальный буфер. Таким образом, буферированные потоки будут безобидно. */ if (len> = cb.length && markedchar <= unmarked &&! skiplf) {return in.read (cbuf, off, len); } fill ();} if (nextChar> = nchars) return -1; if (skiplf) {skiplf = false; if (cb [nextchar] == '/n') {nextchar ++; if (nextchar> = nchars) fill (); if (nextchar> = nchars) return -1; }} int n = math.min (len, nchars - nextchar); System.ArrayCopy (cb, nextchar, cbuf, off, n); nextchar += n; return n; } / *** Читать символы LEN в CBUF к длине LEN от индекса OFF от индекса OFF* / public int Read (char cbuf [], int off, int len) Throws IoException {synchronized (lock) {recaveOpen (); if ((off <0) || (off> cbuf.length) || (len <0) || ((off + len)> cbuf.length) || ((off + len) <0)) {бросить новый indexoutofboundsexception (); } else if (len == 0) {return 0; } int n = read1 (cbuf, off, len); if (n <= 0) return n; while ((n <len) && in.ready ()) {int n1 = read1 (cbuf, off + n, len - n); if (n1 <= 0) break; n + = n1; } return n;}} / *** Читать строку из и игнорировать разрывы строки* / string readline (boolean ignorfelf), бросает ioException {stringBuffer s = null; int startChard; синхронизированный (lock) {убедитесь, что (); Boolean omitlf = INSERONFIELF || skiplf; bufferloop: for (;;) {if (nextchar> = nchars) fill (); if (nextchar> = nchars) { / * eof * / if (s! = null && s.length ()> 0) return s.tostring (); elsereturn null;} boolean eol = false; char c = 0; int i; / * Пропустить остаток '/n', если это необходимо */if (omitlf && (cb [nextchar] == '/n')) nextchar ++; skiplf = false; omitlf = false; Charloop: for (i = nextchar; i <nchars; i ++) {c = cb [i]; if ((c == '/n') || (c == '/r')) {eol = true; сломать Charloop; }} startCHAR = nextCHAN; nextCHAR = i; if (eol) {string str; if (s == null) {str = new String (cb, startchar, i - startchar); } else {s.Append (cb, startchar, i - startchar); str = s.toString (); } nextChar ++; if (c == '/r') {skiplf = true; } return str;} if (s == null) s = new StringBuffer (defaulTexpectedLineLength); S.Append (cb, startchar, i - startchar); }}} / ** * Читать строку из in, * / public String readline () бросает ioException {return readline (false); } / *** Сбросьте n символов в* / public long skip (long n) бросает ioException {if (n <0l) {throw new allogalargumentException («значение пропуска отрицательно»);} синхронизированный (lock) {recaveOpen (); длинный r = n; while (r> 0) {if (nextchar> = nchars) fill (); if (nextchar> = nchars)/ * eof */ break; if (skiplf) {skiplf = false; if (cb [nextchar] == '/n') {nextchar ++; }} long d = nchars - nextchar; if (r <= d) {nextchar += r; r = 0; Break;} else {r -= d; NextChardChr = nchars;}} return n - r;}} / ** * Определите, пуст ли CB или есть ли читаемые символы в базовом в. / * * Если Newline нужно пропустить, а следующий символ для прочтения * - новая линия, то просто пропустите его сразу. */ if (skiplf) {/ * Обратите внимание, что in.share () вернет true, если и только если следующее * Читать в потоке не будет блокировать. */if (nextchar> = nchars && in.ready ()) {fill ();} if (nextchar <nchars) {if (cb [nextchar] == '/n') nextchar ++; skiplf = false;}} return (nextchar <nchars) || in.ready ();}} / *** Определите, поддерживает ли этот поток марки* / public boolean marksupported () {return true; } /*** Отметьте позицию этого потока в настоящее время и позвольте читать символы readaHeadLimit, прежде чем метод сброса сброса не удастся. */ public void mark (int readaHeadlimit) бросает ioException {if (readaHeadlimit <0) {бросить новое allosalargumentException («Читать предел <0»);} synchronized (lock) {recaveOpen (); this.readaHeadLimit = readAHeadLimit; markedchar = nextchar; markedskiplf = skiplf;}} /*** Сбросить позицию, где в последнем помечении. То есть следующий персонаж читается из позиции, которая последней отмеченной. */ public void reset () бросает ioException {synchronized (lock) {recaiveOpen (); if (markedchar <0) бросить новое ioException ((markedchar == недействительно)? NextChar = MarkedChar; skiplf = markedskiplf;}} // Закройте этот поток и выпустить все ресурсы, связанные с этим потоком public void close () бросает ioException {synchronized (lock) {if (in == null) return; in.close (); in = null; cb = null;}}}4. Пример демонстрации:
Пакет com.chy.io.original.test; import java.io.bufferedReader; импорт java.io.bufferedwriter; import java.io.file; импорт java.io.filereader; import java.io.filewriter; import java.io.filewriter; import java.ioexcret; Тест этих двух классов здесь относительно прост, который состоит в том, чтобы обернуть поток символов файла и реализовать копирование файла* Если вы заинтересованы, вы можете проверить эффективность, быть ленивым и игнорировать его*/public static void main (string [] args) бросает ioexception {file resoucefile = new File ("d: //test.txt"); File ("e: //copyoftest.txt"); BufferedReader Br = new BufferedReader (новый FileReader (resoucefile)); BufferedWriter BW = новый BufferedWriter (New FileWriter (TargetFile)); char [] cbuf = new char [1024]; int n = 0; while (n = br. reade (cbuf)! -1) {bw.write (cbuf, 0, n);} // Не забудьте обновить и закрывать поток, в противном случае ресурсы не будут выпущены во времени, с одной стороны, а с другой стороны, это может вызвать потерю данных, если br.close (); bw.flush (); bw.close ();}}, если br.close (); bw.flush (); bw.close ();}}Суммировать:
Для BufferedReader и BufferedWriter сущность состоит в том, чтобы добавить функцию буферизации к базовому вводу и выводу, сначала чтение или записи данных в базовом потоке в форме группы чтения одновременно, а затем работайте в буфере. Это не только эффективность, но и экономит ресурсы. Наконец, в программе, по причинам эффективности, эти два класса должны использоваться для потоков низкого уровня, чтобы украсить их, вместо того, чтобы просто удерживать поток и непосредственно загружать их, думая, что их можно реализовать.