1: BufferWriter
1. Introdução às funções de classe:
BufferWriter, fluxo de saída do caractere de cache, sua função é fornecer função de cache para o fluxo de saída de caracteres subjacente. Da mesma forma, ao usar o fluxo de saída de caracteres subjacente para gravar caracteres ou matrizes de caracteres no destino, a conexão com o destino deve ser aberta toda vez que estiver escrita. Esse acesso frequente é constantemente eficiente e também pode causar certos danos ao meio de armazenamento. Por exemplo, quando escrevemos constantemente bytes no disco, é exagerado escrever uma unidade muito grande de G em um arquivo especificado no disco e, se não escrevermos um byte, o canal para este disco deve ser aberto uma vez. Este resultado é sem dúvida aterrorizante. , e quando usamos o BufferWriter para embrulhar o fluxo de saída de caracteres subjacente, como o FileReader, podemos primeiro escrever os caracteres a serem gravados no arquivo no programa para o espaço de cache interno do BufferWriter e, em seguida, quando um determinado valor for atingido, ele será gravado no fluxo do FilleReader ao mesmo tempo. No momento, o FileReader pode abrir um canal e gravar esse bloco de dados no arquivo. Embora seja impossível alcançar o efeito de escrever todos os dados no disco em um acesso, ele também melhora bastante a eficiência e reduz o número de acessos em disco! Este é o seu significado. Seu princípio de trabalho específico é mencionado brevemente aqui: pode ser bastante confuso aqui. Você pode olhar para o código -fonte em detalhes. Se você não entende, olhe para trás aqui. Sempre que você escrever um caractere ou uma matriz de caracteres em um escritor de buffer no programa, você verificará se a matriz de caracteres em cache BUF (o tamanho do BUF é o padrão ou especificado ao criar um BW, geralmente o padrão é usado) está cheio. Se não estiver cheio, os personagens serão gravados em BUF. If it is full, the underlying writer(char[] b, int off, int is called. len) Write all characters in buf to the underlying out at one time, if the character array is written, if the buf is full, the same as the processing when it is full above, if the written character array can be stored, then store it in buf, if the characters to be stored, and the number of characters to be written to buf is less than the length of buf, then write all characters in BUF a ser escrito para sair e, em seguida, armazenar os personagens a serem escritos no BUF (armazenamento do subscrito 0), se os personagens a serem escritos excedem o comprimento do BUF, depois escreva diretamente para fora,
2. Introdução à API bufferwriter:
A: Palavra -chave Private Writer Out; Fluxo de saída de caracteres inferior CHAR privado CB []; Buffer Array Private Int Nchars, NextChar; NCHARS-Size do tamanho de NChars, NextChar-subscript do próximo caractere no CB privado estático int defaultcharbuffersize = 8192; Tamanho padrão do CB Private String lineseparator; NEWLINE CARACTER, usado para o método Newline. Plataformas diferentes têm valores diferentes. B: Construct Method BufferWriter (Writer Out) Cria bufferwriter bw usando o tamanho padrão do CB. BufferWriter (Writer Out, Int SZ) cria bufferwriter BW usando o tamanho padrão do CB. C: O método geral void Close () fecha esse fluxo e libera recursos relacionados a esse fluxo. Void FlushBuffer () Libere os caracteres em cache no CB no Out Subjacente, o Void Flush () atualiza esse fluxo e atualiza o fluxo subjacente void newline () grava um caractere novo. Void Write (int c) grava um único caractere no CB. Void Write (char cbuf [], int off, int len) Escreva um comprimento de personagem de Len do subscrito desligado para CB void Write (String S, Int Off, Int Len) Escreva uma parte de uma string para CB
3. Análise do código -fonte
pacote com.chy.io.original.code; importar java.io.ioException; importar java.io.printwriter;/*** Forneça função buffer para fluxos de saída de caracteres e melhore a eficiência. Você pode usar o caractere especificado para buffer o tamanho da matriz ou o caractere padrão para buffer o tamanho da matriz. */public class BufferWriter estende o Writer {// Base Array Private Writer; // Buffer Array Private Char CB []; // NCHARS-O número total de caracteres em CB, NextChar-o subscrito do próximo caractere em CB Private Int Nchars, NextChar; // tamanho padrão CB private estático int defaultcharbuffersize = 8192; /*** String de separador de linha. Esse é o valor da propriedade. Separador * Propriedade no momento em que o fluxo foi criado. * Linha o caractere newline, usado para o método newline. Plataformas diferentes têm valores diferentes. */ private String lineseparator; /*** Crie bufferwriter bw com o tamanho padrão do CB. */ public bufferwriter (writer Out) {this (out, defaultcharbuffersize); } / ** * Crie BR e inicialize campos relacionados com o tamanho do CB especificado * / public bufferwriter (Writer Out, int sz) {super (out); if (sz <= 0) lançar novo ilegalArgumentException ("tamanho do buffer <= 0"); this.out = out; cb = novo char [sz]; nchars = sz; nextchar = 0; // Obtenha a representação de caracteres de nova linha sob diferentes plataformas. LineSeparator = (String) java.security.accessController.doprivileged (new sun.security.action.getPropertyAction ("line.separator")); } / ** Detecte se o fluxo de saída de caracteres subjacente está fechado* / private void garantir () lança ioexception {if (out == null) lança nova ioexception ("stream fechado"); } /*** Lembre -se dos caracteres em cache no CB para a saída subjacente, mas não liberam os caracteres no escuro subjacente. * E claro cb. */ void FlushBuffer () lança IoException {Sincronized (Lock) {garantir (); if (nextChar == 0) retornar; out.Write (CB, 0, NextChar); NextChar = 0;}} /*** Escreva um único caractere para CB. */ public void write (int c) lança ioexception {sincronizada (bloqueio) {preveropen (); if (nextchar> = qchars) flushBuffer (); cb [nextChar ++] = (char) c;}} /** * Nosso próprio método min, para evitar carregar java.lang.math se executamos * fora dos descritores de arquivos e estamos tentando imprimir um rastreamento de pilha. */ private int min (int a, int b) {if (a <b) retornar a; retornar b; } / *** Escreva um comprimento de caractere do len do subscrito desligado para cb* / public void write (char cbuf [], int off, int len) lança a ioexception {synchronized (bloqueio) {preveropen (); if ((off <0) || (off> cbuf.length) || (len <0) || ((off + len)> cbuf.length) || ((off + len) <0)) {lança novo indexOutOfBoundSception (); } else if (len == 0) {return; } if (len> = nchars) {/* Se len for maior que o comprimento do CB, os caracteres existentes em CB e caracteres no CBUF são diretamente gravados para sair, em vez de escrever para CB e depois escrever para fora. */flushBuffer (); out.write (cbuf, desligado, len); retorno; } int b = desativado, 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 (); }}} / *** Escreva parte de uma string para cb* / public void write (string s, int off, int len) lança ioexception {synchronized (bloqueio) {garantir (); int b = desligado, 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 (); }}} /*** Escreva uma nova linha. */ public void newline () lança IoException {write (lineseparator); } / *** Atualize este fluxo e atualize o fluxo subjacente ao mesmo tempo* / public void Flush () lança IoException {Synchronized (Lock) {FlushBuffer (); out.flush ();}} /*** Feche este fluxo e libere recursos relacionados a este fluxo. */ public void Close () lança IoException {Synchronized (Lock) {if (out == null) {return; } tente {flushBuffer (); } finalmente {out.close (); out = null; cb = nulo; }}}}4. Exemplo de demonstração: use o seguinte BufferErader para implementar a cópia de arquivos do tipo caractere.
Dois: BufferredReader
1. Introdução às funções de classe:
Fluxo de entrada de caracteres em buffer, sua função é fornecer função de buffer para o fluxo de entrada de caracteres subjacente subjacente. Ele lerá os caracteres no fluxo de entrada de caracteres subjacentes (IN) em seu próprio buffer (matriz de caracteres em cache embutido) e, em seguida, o programa chama o método de leitura do BufferErader para ler os caracteres no buffer no programa. Quando os caracteres do buffer são lidos, o BufferErader leia o próximo bloco de dados de dentro e para o buffer para o programa ler até que os dados sejam lidos. Os benefícios de fazer isso são, primeiro, melhora a eficiência da leitura e, segundo, reduz o número de conexões para abrir o meio de armazenamento. Por razões detalhadas, o BufferWriter mencionado abaixo. Existe um método -chave preenchimento (), que é preencher os dados de In e preencher os dados do buffer sempre que os dados no buffer são lidos dez vezes mais rápido do que o que o lê do disco! Esta é uma melhoria muito aterrorizante na eficiência. Ao mesmo tempo, não podemos especificar o tamanho do buffer do BufferredReader sem proibir. Afinal, leva muito tempo para ler o único. Em segundo lugar, o preço da memória é relativamente caro. O que podemos fazer é tentar encontrar pontos razoáveis nele. Geralmente, não precisamos nos preocupar com isso e usar o tamanho padrão do buffer ao criar um leitor de buffers.
2. Introdução à API BufferredReader:
R: Construindo o Método BufferReader (leitor in, int sz) cria um leitor de buffers com base no tamanho especificado e no fluxo de entrada de caracteres subjacente. br BufferedReader(Reader in) Use the default size to create the buffered stream of the underlying output stream B: General method void close() close this stream and release all resources related to this stream void mark(int readAheadLimit) mark the position of this stream at this time boolean markSupported() determines whether this stream supports marking void reset() reset in reset in the position of the last mark boolean ready() determines whether this stream can read caracteres int read () lê um único caractere e retorna em um formulário inteiro. Se o fim de in for lido, ele retornará -1. int leia (char [] cbuf, int off, int len) leu caracteres len no cbuf a partir do subscrito desligado, comprimento len string readline () leia um skip de longa (longa) descarte n caracteres no cbuf
3. Análise do código -fonte
pacote com.chy.io.original.code; importar java.io.ioException;/*** Adicione a matriz CB buffer de caracteres para o fluxo de entrada de caracteres subjacente. Melhorar a eficiência * @Version 1.1, 13/11/17 * @authorandychen */public class BufferReader estende o leitor {Private Reader in; CHAR privado CB []; private Int Nchars, NextChar; private estático final int invalidado = -2; private estático final int não marcado = -1; private int markedchar = não marcado; private int readeaheadlimit = 0; /*Válido somente quando marcado> 0*// ** Se o próximo caractere for um feed de linha, pule -o*/ private booleano skiplf = false; / ** O sinalizador skiplf quando a marca foi definida*/ private boolean markedskiplf = false; private estático int defaultcharbuffersize = 8192; private estático int defaultExpeedLinElength = 80; /*** Crie um leitor de buffers com base no tamanho especificado e no fluxo de entrada de caracteres subjacente. Br */ public buffaredReader (leitor in, int sz) {super (in); if (sz <= 0) lançar novo ilegalArgumentException ("tamanho do buffer <= 0"); this.in = in; cb = new char [sz]; nextchar = nchars = 0; } / *** Use o tamanho padrão para criar um fluxo em buffer do fluxo de saída subjacente* / public bufferreader (leitor in) {this (in, defaultcharbuffersize); } / ** Detecte se o fluxo de entrada de caracteres subjacente está fechado* / private void garantir () lança ioexception {if (in == null) lança uma nova ioexception ("stream fechada"); } /*** Preencha CB. */ private void preht () lança ioexception {int dst; if (markedchar <= não marcado) {/ *sem mark */ dst = 0;} else {/ *marcado */ int delta = nextChar - markedchar; if (delta> = readaHeadlimit) {/ * foi além do limite de leitura de leitura: invalidar mark */markedchar = invalidado; readaheadlimit = 0; dst = 0; } else {if (readaHeadlimit <= cb.length) { / * embaralhamento no buffer atual * / system.arraycopy (cb, markedchar, cb, 0, delta); markedchar = 0; dst = delta;} else { / * RealLocate buffer para acomodar o limite de leitura * / char ncb [] = novo 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; NextChar = dst;}} /*** Leia um único caractere e retorne como um número inteiro. Se o fim de in for lido, ele retornará -1. */ public int read () lança IoException {Synchronized (Lock) {garantiropen (); para (;;) {if (nextchar> = nchars) {preench (); if (nextchar> = nchars) retornar -1;} if (skiplf) {skiplf = false; if (cb [nextChar] == '/n') {nextChar ++; continue; }} retornar 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 os personagens no buffer local. Dessa maneira, os riachos buffers serão inofensivos em cascata. */ if (len> = cb.length && markedchar <= não marcado &&! skiplf) {return in.read (cbuf, off, len); } preench ();} if (nextchar> = nchars) retornar -1; if (skiplf) {skiplf = false; if (cb [nextChar] == '/n') {nextchar ++; if (nextchar> = nchars) preench (); if (nextchar> = nchars) retornar -1; }} int n = math.min (len, nchars - nextchar); system.arraycopy (cb, nextchar, cbuf, off, n); nextchar += n; return n; } / *** Leia os caracteres len em CBUF para comprimento len do índice off do subscrito desligado* / public int leia (char cbuf [], int off, int len) lança ioexception {sincronizada (bloqueio) {garantir (); if ((off <0) || (off> cbuf.length) || (len <0) || ((off + len)> cbuf.length) || ((off + len) <0)) {lança novo indexOutOfBoundSception (); } else if (len == 0) {return 0; } int n = read1 (cbuf, desligado, len); if (n <= 0) retornar n; while ((n <len) && in.ready ()) {int n1 = read1 (cbuf, off + n, len - n); if (n1 <= 0) quebra; n + = n1; } retornar n;}} / *** Leia uma linha de in e ignore quebras de linha* / string readline (boolean ignorelf) lança ioexception {stringbuffer s = null; int startchar; sincronizado (bloqueio) {garantir (); omitlf booleano = ignorante || skiplf; bufferloop: para (;;) {if (nextchar> = nchars) preench (); if (nextchar> = nchars) { / * eof * / if (s! = null && s.length ()> 0) retornar s.toString (); elsereturn null;} boolean eol = false; char c = 0; int i; / * Pule um restante '/n', se necessário */if (omitlf && (cb [nextChar] == '/n')) nextchar ++; skiplf = false; omitlf = false; Charloop: para (i = nextchar; i <nchars; i ++) {c = cb [i]; if ((c == '/n') || (c == '/r')) {eol = true; quebre 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 (defaultExpeedLineLength); S.Append (CB, StartChar, i - StartChar); }}} / ** * Leia uma linha de in, * / public string readLine () lança ioexception {return readLine (false); } / *** descarte n caracteres in* / public Long Skip (Long n) lança a ioexception {if (n <0l) {lança nova ilegalArgumentException ("o valor do skip é negativo");} sincronizado (bloqueio) {garantir (); r = n; while (r> 0) {if (nextchar> = nchars) preench (); 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; quebra;} else {r -= d; nextchar = nchars;}} retornar n - r;}} / ** * Determine se o CB está vazio ou se existem caracteres legíveis no subjacente. / * * Se a Newline precisar ser ignorada e o próximo char para ser lido * é um caractere novo, basta ignorá -lo imediatamente. */ if (skiplf) {/ * Observe que o in.ready () retornará true se e somente se o próximo * leia no fluxo não bloquear. */if (nextChar> = nchars && in.ready ()) {preench ();} if (nextChar <nchars) {if (cb [nextChar] == '/n') nextChar ++; skiplf = false;}} retornar (NextChar <nchars) || in.ready ();}} / *** Determine se esse fluxo suporta marcas* / public boolean MarkSupported () {return true; } /*** Marque a posição desse fluxo no momento e permita a leitura para os caracteres leiaHeadlimit antes que a chamada para redefinir o método falhe. */ public void Mark (int readeaHeadlimit) lança a ioException {if (readaHeadlimit <0) {lança nova ilegalArgumentException ("LIMITE DE READ-AHEAD <0");} sincronizada (Lock) {garantir-se (); this.readheadlimit = readaheadlimit; Markedchar = NextChar; markedskiplf = skiplf;}} /*** redefinir a posição onde foi marcado pela última vez. Ou seja, o próximo personagem é lido da posição que está marcada pela última vez. */ public void reset () lança IoException {Synchronized (Lock) {garantiropen (); if (markedchar <0) lançar uma nova ioexception ((markedchar == invalidado)? "Mark inválido": "stream não marcado"); nextchar = markedchar; skiplf = markedskiplf;}} // Fechar este fluxo e liberar todos os recursos relacionados a este fluxo public void close () lança ioexception {sincronizada (bloqueio) {if (in == null) return; in.Close (); in = null; cb = null;}}}4. Exemplo de demonstração:
pacote com.chy.io.original.test; importar java.io.bufferedreader; importar java.io.bufferedwriter; importar java.io.file; importar java.io.fileReader; import java.io.io.fileWriter; import java.io.filiterTerTer; O teste dessas duas classes aqui é relativamente simples, que é embrulhar o fluxo de caracteres do arquivo e implementar a cópia de arquivos* Se estiver interessado, você pode testar a eficiência, ser preguiçoso e ignorá -lo*/public static void main (string [] args) lança ioexception {file resoucefile = novo arquivo ("d: //test.ttx); File ("e: //copyoftest.txt"); buffarredreader br = new bufferredreader (novo fileReader (resoucefile)); bufferwriter bw = new buffarredwriter (new FileWriter (TargetFile); char [] cbu = new char [1024]; int n = 0; -1) {bw.write (cbuf, 0, n);} // Não se esqueça de refrescar e fechar o fluxo; caso contrário, os recursos não serão liberados a tempo, por um lado, e por outroResumir:
Para o BufferredReader e o BufferWriter, a essência é adicionar a função buffersing ao fluxo de entrada e saída de caracteres subjacentes, primeiro ler ou gravar dados no fluxo subjacente na forma de um grupo de leituras por vez e depois opere no buffer. Isso não apenas eficiência, mas também salva recursos. Finalmente, no programa, por razões de eficiência, essas duas classes devem ser usadas para fluxos de baixo nível para decorá-los, em vez de apenas segurar o fluxo e carregá-los diretamente, pensando que eles podem ser realizados.