1: escritor buffered
1. Introducción a las funciones de clase:
BufferedWriter, flujo de salida de caracteres de caché, su función es proporcionar la función de caché para la secuencia de salida de caracteres subyacente entrante. Del mismo modo, cuando se usa la transmisión de salida de caracteres subyacente para escribir caracteres o matrices de caracteres al destino, la conexión al destino debe abrirse cada vez que se escribe. Tal acceso frecuente es constantemente eficiente, y también puede causar cierto daño al medio de almacenamiento. Por ejemplo, cuando constantemente escribimos bytes en el disco, es exagerado escribir una unidad muy grande de G a un archivo especificado en el disco, y si no escribimos un byte, el canal a este disco debe abrirse una vez. Este resultado es indudablemente aterrador. , y cuando usamos BufferedWriter para envolver la secuencia de salida de caracteres subyacente, como FileReader, primero podemos escribir los caracteres para que se escriban en el archivo en el programa al espacio de caché incorporado del compatidor buffered, y luego, cuando se alcanza una cierta cantidad, se escribirá en la corriente de FileReader en un momento. En este momento, FileReader puede abrir un canal y escribir este bloque de datos en el archivo. Aunque es imposible lograr el efecto de escribir todos los datos en el disco en un solo acceso, ¡también mejora enormemente la eficiencia y reduce el número de accesos de disco! Este es su significado. Aquí se menciona brevemente su principio de trabajo específico: puede ser bastante confuso aquí. Puede mirar el código fuente en detalle. Si no lo entiende, mire hacia atrás aquí. Cada vez que escriba una matriz de personajes o un personaje en un escritor buffered en el programa, verificará si la matriz de caracteres en caché BUF (el tamaño de BUF es el valor predeterminado o especificado al crear un BW, generalmente el valor predeterminado) está lleno. Si no está lleno, los personajes se escriben en BUF. Si está lleno, el escritor subyacente (char [] b, int, int se llama. en BUF para ser escrito para salir, y luego almacene los personajes que se escribirán en BUF (almacenamiento del subíndice 0), si los personajes que se escriben en la longitud de BUF, luego escriban directamente a Out,
2. Introducción a la API de escritor buffered:
A: Palabra clave escritor privado; Flujo de salida de carácter inferior Char privado CB []; Matriz de búfer private int nchars, nextchar; nchars-tamaño del tamaño de nchars, nextchar-subscript del siguiente carácter en CB private static int defaultCharBufferSize = 8192; Tamaño predeterminado de CB String Private String LineseParator; NUEVA CARACTER, utilizado para el método Newline. Diferentes plataformas tienen diferentes valores. B: Método de construcción BufferedWriter (Writer Out) Crea BufferedWriter BW utilizando el tamaño CB predeterminado. BufferedWriter (Writer Out, Int Sz) crea BUFEDWriter BW utilizando el tamaño CB predeterminado. C: El método general void Close () cierra esta transmisión y libera recursos relacionados con esta transmisión. Void FlushBuffer () Flush Los caracteres almacenados en caché en CB en el flush subyacente, Void Flush () refresca esta corriente y actualiza la transmisión subyacente Void Newline () escribe un carácter de Newline. Void Write (Int C) escribe un solo carácter en CB. void write (char cbuf [], int off, int len) Escribir una longitud de caracteres de len desde el subíndice Off a CB void Write (String S, int Off, int Len) Escriba una parte de una cadena a CB
3. Análisis del código fuente
paquete com.chy.io.original.code; import java.io.ioexception; import java.io.printwriter;/*** Proporcionar función de almacenamiento en búfer para las flujos de salida de caracteres y mejorar la eficiencia. Puede usar el carácter especificado para amortiguar el tamaño de la matriz o el carácter predeterminado para amortiguar el tamaño de la matriz. */Public Class BufferedWriter extiende al escritor {// Base Array Private Writer Out; // matriz búfer private char cb []; // nchars-el número total de caracteres en CB, Nextchar-el subíndice del siguiente carácter en CB private int nchars, Nextchar; // tamaño predeterminado de CB static int defaultCharBufferSize = 8192; /*** cadena separadora de línea. Este es el valor de la propiedad Line.separator * en el momento en que se creó la transmisión. * Línea al carácter de Newline, utilizado para el método Newline. Diferentes plataformas tienen diferentes valores. */ Private String LineseParator; /*** Crea BufferedWriter BW con el tamaño CB predeterminado. */ public BufferedWriter (Writer Out) {this (Out, DefaultCharBufferSize); } / ** * Crear BR e inicializar campos relacionados con el tamaño CB especificado * / public BufferedWriter (Writer Out, int sz) {super (out); if (sz <= 0) tirar nueva ilegalArgumentException ("tamaño de amortiguación <= 0"); this.out = out; cb = new Char [sz]; nchars = sz; nextchar = 0; // Obtenga la representación de caracteres Newline en diferentes plataformas. LineeParator = (String) java.security.accessController.Doprivileged (nuevo sun.security.action.getPropertyaction ("line.separator")); } / ** Detectar si la secuencia de salida de caracteres subyacente está cerrada* / private void asegurar () lanza ioexception {if (out == null) throw IoException ("Stream cerrado"); } /*** Enjuague los caracteres en caché en CB a la salida subyacente, pero no enjuague a los personajes en la salida subyacente. * Y claro CB. */ void flushbuffer () lanza IOException {Synchronized (Lock) {ASCANSE (); if (nextchar == 0) return; out.write (CB, 0, NextChar); nextchar = 0;}} /*** Escriba un solo carácter a CB. */ public void write (int c) lanza ioexception {sincronizado (bloqueo) {asacOpen (); if (nextchar> = nchars) flushbuffer (); CB [NextChar ++] = (char) C;}} /** * Nuestro propio pequeño método min, para evitar cargar java.lang.math si hemos ejecutado * fuera de los descriptores de archivos e intentamos imprimir una traza de pila. */ private int min (int a, int b) {if (a <b) return a; return b; } / *** Escriba una longitud de caracteres de LEN desde el subíndice apagado a CB* / public void Write (char cbuf [], int off, int len) lanza ioexception {sincronizado (bloqueo) {asacUal (); if ((off <0) || (Off> cbuf.length) || (len <0) || ((Off + len)> cbuf.length) || ((OFF + len) <0)) {tire el nuevo indexOutofBoundseException (); } else if (len == 0) {return; } if (len> = nchars) {/* Si el len es mayor que la longitud de CB, entonces los caracteres existentes en CB y los caracteres en CBUF se escriben directamente en Out, en lugar de escribir a CB, y luego escribiendo en Out. */flushbuffer (); out.write (cbuf, off, len); return; } int b = apagado, t = apagado + 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 (); }}} / *** Escribir parte de una cadena a CB* / public void Write (String S, int Off, int Len) lanza ioexception {sincronizado (bloqueo) {asegurar (); int b = apagado, t = apagado + 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 (); }}} /*** Escribe una nueva línea. */ public void newline () lanza IOException {Write (LineeParator); } / *** Actualice esta transmisión y actualice la transmisión subyacente al mismo tiempo* / public void flush () lanza ioexception {sincronizado (bloqueo) {flushbuffer (); out.flush ();}} /*** Cierre esta transmisión y libera recursos relacionados con esta transmisión. */ public void Close () lanza ioexception {sincronizado (bloqueo) {if (out == null) {return; } try {FlushBuffer (); } finalmente {out.close (); out = nulo; cb = nulo; }}}}4. Demostración de ejemplo: use el siguiente BufferedReader para implementar la copia de los archivos de tipo de carácter.
Dos: BufferedReader
1. Introducción a las funciones de clase:
Flujo de entrada de caracteres bustificado, su función es proporcionar una función de almacenamiento en búfer para la secuencia de entrada de caracteres subyacente entrante. Leerá los caracteres en la secuencia de entrada de caracteres subyacente (in) en su propio búfer (matriz de caracteres en caché incorporado), y luego el programa llama al método de lectura del BufferedReader para leer los caracteres en el búfer en el programa. Cuando se leen los caracteres en el búfer, el BufferedReader leerá el siguiente bloque de datos desde adentro y en el búfer para que el programa se lea hasta que se lean los datos. Los beneficios de hacer esto son, primero, mejora la eficiencia de lectura, y en segundo lugar, reduce el número de conexiones para abrir el medio de almacenamiento. Por razones detalladas, BufferedWriter mencionado a continuación. Existe un método clave relleno (), que es llenar los datos de In y llenar los datos del búfer cada vez que los datos en el búfer se leen diez veces más rápido de lo que se lee desde el disco. Esta es una mejora muy aterradora en la eficiencia. Al mismo tiempo, no podemos especificar el tamaño del búfer del lector buffered sin prohibir. Después de todo, lleva mucho tiempo leer en una sola vez. En segundo lugar, el precio de la memoria es relativamente costoso. Lo que podemos hacer es tratar de encontrar puntos razonables en él. En general, no tenemos que preocuparnos por eso y usar el tamaño predeterminado del búfer al crear un BufferedReader.
2. Introducción a la API de BufferedReader:
R: El método de construcción de BufferedReader (Reader IN, Int Sz) crea un letrero buffered basado en el tamaño especificado y la secuencia de entrada de caracteres subyacente. BR BufferedReader (Reader in) Use el tamaño predeterminado para crear la secuencia buffered de la transmisión de salida subyacente B: Método general void Close () Cerrar esta secuencia y liberar todos los recursos relacionados con esta transmisión void Mark (int ReadAheadlimit) marcar la posición de esta transmisión en este momento Boolean Marksupported () determina si esta corriente es compatible con este flujo de transmisión de transmisión (). Leer caracteres int read () lee un solo carácter y regresa en forma entera. Si el final de In se lee, devuelve -1. int read (char [] cbuf, int off, int len) leer caracteres de len en cbuf a partir de subíndice apagado, longitud len string readline () Leer una línea de omisión larga (long n) descarte n caracteres en cbuf
3. Análisis del código fuente
paquete com.chy.io.original.code; import java.io.ioException;/*** Agregar matriz CB de almacenamiento en búfer de caracteres para la secuencia de entrada de caracteres subyacente. Mejorar la eficiencia * @version 1.1, 13/11/17 * @authorandychen */public class BufferedReader extiende el lector {lector privado en; privado char cb []; private int nchars, Nextchar; Private estático final int Invalidated = -2; Private estático final int unmarked = -1; private int markedchar = sin marcar; privado int readAheadlimit = 0; /*Válido solo cuando MarkedChar> 0*// ** Si el siguiente carácter es una alimentación de línea, omitirlo*/ private boolean skiplf = false; / ** El indicador de Skiplf cuando se estableció la marca*/ Private Boolean MarkedSkiPlf = false; Private static int defaultCharBufferSize = 8192; PRIVADA ESTÁTICA INTFORTH OFFUERTEPECTECTIONLELGHY = 80; /*** Crear un lector de topeed basado en el tamaño especificado y la secuencia de entrada de caracteres subyacente. Br */ public BufferedReader (lector en, int sz) {super (in); if (sz <= 0) tirar nueva ilegalArgumentException ("tamaño de amortiguación <= 0"); this.in = in; cb = new char [sz]; nextchar = nchars = 0; } / *** Use el tamaño predeterminado para crear una secuencia buffed de la transmisión de salida subyacente* / public BufferedReader (lector in) {this (in, defaultCharBufferSize); } / ** Detectar si la secuencia de entrada de caracteres subyacente está cerrada* / private void asegurar () lanza ioexception {if (in == null) tirar nueva ioexception ("flujo cerrado"); } /*** Complete CB. */ private void relleno () lanza ioexception {int dst; if (markedchar <= sinmarked) {/ *no mark */ dst = 0;} else {/ *marcado */ int delta = nextchar - marcedchar; if (delta> = readeHeadlimit) {/ * Pasado Límite de lectura: Invalidate Mark */MarkedChar = Invalidated; ReadAheadLimit = 0; dst = 0; } else {if (readAheadLimit <= cb.length) { / * shuffle en el búfer actual * / system.ArrayCopy (CB, MarkedChar, CB, 0, delta); Markedchar = 0; dst = delta;} else { / * Buffer de reasignado para acomodar el límite de lectura * / char ncb [] = new Char [readeheadlimit]; 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; nextchar = dst;}} /*** Lea un solo carácter y regrese como entero. Si el final de In se lee, devuelve -1. */ public int read () lanza IOException {SynChronized (Lock) {ASCANSEPEN (); for (;;) {if (nextchar> = nchars) {relleno (); if (nextchar> = nchars) return -1;} if (skiplf) {skiplf = false; if (cb [nextchar] == '/n') {nextchar ++; continuar; }} return cb [nextchar ++]; }} } /** * Read len characters in in to cbuf from the length len starting from the subscript off*/ private int read1(char[] cbuf, int off, int len) throws IOException {if (nextChar >= nChars) { /* If the requested length is at least as large as the buffer, and if there is no mark/reset activity, and if line feeds are not being skipped, do not both to copy los personajes en el búfer local. De esta manera, las corrientes amortiguadas en cascada en cascada. */ if (len> = cb.length && markedchar <= unmarked &&! skiplf) {return in.read (cbuf, off, len); } relleno ();} if (nextchar> = nchars) return -1; if (skiplf) {skiplf = false; if (cb [nextchar] == '/n') {nextchar ++; if (nextchar> = nchars) relleno (); if (nextchar> = nchars) return -1; }} int n = math.min (len, nchars - nextchar); system.arrayCopy (cb, nextchar, cbuf, off, n); nextchar += n; return n; } / *** Leer personajes de LEN en en Cbuf para longitud de longos desde el índice OFF de la subíndice OFF* / public int read (char cbuf [], int off, int len) lanza ioexception {sincronizado (bloqueo) {asacUdOpen (); if ((off <0) || (Off> cbuf.length) || (len <0) || ((Off + len)> cbuf.length) || ((OFF + len) <0)) {tire el nuevo indexOutofBoundseException (); } 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) ruptura; n + = n1; } return n;}} / *** Lea una línea desde adentro e ignore las rupturas de línea* / string readline (boolean ignorelf) lanza ioexception {stringbuffer s = null; int startchar; sincronizado (bloqueo) {asegurar (); boolean omitlf = ignorelf || skiplf; bufferloop: for (;;) {if (nextchar> = nchars) relleno (); if (nextchar> = nchars) { / * eof * / if (s! = null && s.length ()> 0) return s.ToString (); Elsereturn null;} boolean eol = false; char c = 0; int i; / * Omita una sobrante '/n', si es necesario */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; break Charloop; }} startchar = nextchar; 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 (DefaultEppectedLinelength); s.append (cb, startchar, i - startchar); }}} / ** * Leer una línea desde In, * / public String Readline () lanza ioexception {return readline (false); } / *** Descarte n caracteres en* / public Long Skip (Long n) arroja ioexception {if (n <0l) {tirar nueva ilegalArgumentException ("Skip Value es negativo");} Sincronizado (bloqueo) {asfraePen (); largo r = n; while (r> 0) {if (nextchar> = nchars) relleno (); 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; nextchar = nchars;}} return n - r;}} / ** * Determine si CB está vacío o si hay caracteres legibles en el subyacente. * / public Boolean Ready () lanza IOException {sincronizado (bloqueo) {asegurar (); / * * Si se necesita omitir Newline y el siguiente char para leer * es un personaje de Newline, entonces omita de inmediato. */ if (skiplf) {/ * Tenga en cuenta que en.ready () devolverá verdadero si y solo si el siguiente * lee en la transmisión no bloqueará. */if (nextchar> = nchars && in.ready ()) {relleno ();} if (nextchar <nchars) {if (cb [nextchar] == '/n') nextchar ++; skiplf = false;}} return (nextchar <nchars) || in.ready ();}} / *** Determine si este flujo admite marcas* / public boolean MarkSupported () {return true; } /*** Marque la posición de esta transmisión en este momento, y permita leer a los caracteres de readeheadlimit antes de que falle el método de llamada a restablecer. */ public void Mark (int readAheadlimit) lanza IOException {if (readeheadlimit <0) {tirar nueva ilegalArgumentException ("Límite de lectura <0");} Synchronized (Lock) {ASCANSE (); this.readeHeadLimit = readeHeadLimit; markedchar = nextchar; MarkedSkiPlf = skiplf;}} /*** Restablezca la posición donde se marcó por última vez. Es decir, el siguiente personaje se lee desde la posición que se marca por última vez. */ public void reset () lanza IOException {SynChronized (Lock) {ASCANSEPEN (); if (markedchar <0) tirar nueva ioexception ((markedchar == invalidada)? "Mark Invalid": "Stream no marcada"); nextchar = markedchar; skiplf = MarkedSkiPlf;}} // Cierre esta transmisión y libera todos los recursos relacionados con este stream public void Close () lanza ioexception {sincronizado (bloqueo) {if (in == null) return; cercar(); in = nulo; cb = null;}}}4. Demostración de ejemplo:
paquete com.chy.io.original.test; import java.io.bufferedReader; import java.io.bufferedwriter; import java.io.file; import java.io.filereader; import java.io.filewriter; import java.io.io.writer; import java.io.io.ioxception; public class BufferedWriterester; La prueba de estas dos clases aquí es relativamente simple, que es envolver la transmisión de caracteres del archivo e implementar la copia de archivos* Si está interesado, puede probar la eficiencia, ser perezoso e ignorarlo*/public static void main (string [] args) lanza IOException {archivo resouceFile = nuevo archivo ("d: //test.txt"); archivo de archivo = nuevofile = nuevo film Archivo ("E: //Copyoftest.txt"); BufferedReader BR = New BufferedReader (new FileReader (resouceCe)); BufferedWriter BW = new BufferedWriter (New FileWriter (TargetFile)); Char [] CBUF = New Char [1024]; int n = 0; while (n = Br.Read (CBUF))! -1) {bw.write (cbuf, 0, n);} // No olvide actualizar y cerrar el flujo, de lo contrario los recursos no se lanzarán a tiempo por un lado, y por otro lado, puede causar pérdida de datos si br.close (); bw.flush (); bw.close ();}}Resumir:
Para BufferedReader y BufferedWriter, la esencia es agregar la función de almacenamiento en búfer a la secuencia de entrada y salida de caracteres subyacente, primero lee o escriba datos en la secuencia subyacente en forma de un grupo de lecturas a la vez, y luego opere en el búfer. Esto no solo la eficiencia, sino que también ahorra recursos. Finalmente, en el programa, por razones de eficiencia, estas dos clases deben usarse para transmisiones de bajo nivel para decorarlas, en lugar de solo mantener la corriente y cargarlas directamente, pensando que pueden realizarse.