1: Bufferterwriter
1. Einführung in Klassenfunktionen:
BufferedWriter, Cache -Zeichenausgangsstrom, seine Funktion besteht darin, die Cache -Funktion für den eingehenden Charakterausgangsstrom zu liefern. In ähnlicher Weise muss die Verbindung zum Ziel jedes Mal geöffnet werden, wenn es geschrieben wird, wenn der zugrunde liegende Charakterausgabe -Stream zum Schreiben von Zeichen oder Zeichenarrays an das Ziel verwendet wird. Ein solcher häufiger Zugang ist ständig effizient und kann auch einen gewissen Schaden an das Lagermedium verursachen. Wenn wir beispielsweise ständig Bytes auf die Festplatte schreiben, ist es übertrieben, eine sehr große Einheit G auf eine bestimmte Datei auf der Festplatte zu schreiben, und wenn wir kein Byte schreiben, muss der Kanal auf diese Festplatte einmal geöffnet werden. Dieses Ergebnis ist zweifellos erschreckend. Und wenn wir den BufferedWriter verwenden, um den zugrunde liegenden Zeichenausgangsstrom wie FileReader zu wickeln, können wir zunächst die Zeichen schreiben, die in die Datei im Programm in den integrierten Cache-Raum des BufferedWriter geschrieben werden sollen, und wenn ein bestimmter Betrag erreicht ist, wird er zu einem Zeitpunkt in den FileReader-Stream geschrieben. Zu diesem Zeitpunkt kann FileReader einen Kanal öffnen und diesen Datenblock in die Datei schreiben. Obwohl es unmöglich ist, die Auswirkung des Schreibens aller Daten in einem Zugriff auf die Festplatte zu erreichen, verbessert es auch die Effizienz erheblich und verringert die Anzahl der Datenträgerzugriffe! Dies ist seine Bedeutung. Sein spezifisches Arbeitsprinzip wird hier kurz erwähnt: Hier kann es ziemlich verwirrend sein. Sie können den Quellcode im Detail betrachten. Wenn Sie es nicht verstehen, schauen Sie hier zurück. Wenn Sie im Programm ein Zeichen oder ein Charakter -Array in einen gepufferten Writer schreiben, überprüfen Sie, ob das zwischengespeicherte Zeichen -Array -BUF (die Größe der BUF ist die Standardeinstellung, die beim Erstellen eines BW angegeben ist, im Allgemeinen wird der Standard verwendet) voll) voll). Wenn es nicht voll ist, werden die Zeichen in BUF geschrieben. Wenn es voll ist, wird der zugrunde liegende Schriftsteller (char [] b, int off, int genannt. BUF, um auszuschreiben, und dann die Zeichen zu speichern, die in BUF geschrieben werden sollen (Speicher aus dem Index 0), wenn die Zeichen, die ausgeschrieben werden sollen, über die Länge von Buf überschreiten, dann schreiben Sie direkt auf Out.
2. Einführung in die BufferedWriter -API:
A: Keyword Private Writer Out; Niedrigerer Zeichenausgangsstrom private char cb []; Puffer Array Private int nchars, NextChar; NCHARS-Größe der Größe von NCHARS, NextChar-Subscript des nächsten Zeichens in CB Private statische Int defaultCharBufferSize = 8192; Standard -CB -Größe privater String -Liniensparator; Newline -Zeichen, verwendet für die Newline -Methode. Verschiedene Plattformen haben unterschiedliche Werte. B: Construct -Methode BufferedWriter (Writer Out) erstellt BufferedWriter BW unter Verwendung der Standard -CB -Größe. BufferedWriter (Writer Out, INT SZ) erstellt BufferedWriter BW mithilfe der Standard -CB -Größe. C: Die allgemeine Methode void close () schließt diesen Stream und setzt Ressourcen im Zusammenhang mit diesem Strom frei. void Flushbuffer () spülen die zwischengespeicherten Zeichen in CB in die darunter liegende, void Flush () aktualisiert diesen Stream und aktualisiert den zugrunde liegenden Stream void Newline () einen neuen Charakter. void write (int c) schreibt ein einzelnes Zeichen in CB. void write (char cbuf [], int off, int len) schreiben eine Zeichenlänge von len aus dem Index aus CB Void Write (String S, Off, int len) Schreiben Sie einen Teil einer Zeichenfolge zu CB
3. Quellcodeanalyse
Paket com.chy.io.original.code; import java.io.ioxception; import java.io.printwriter;/*** Bieten Sie Pufferfunktion für Zeichenausgangsströme und verbessern Sie die Effizienz. Sie können das angegebene Zeichen verwenden, um die Arraygröße oder das Standardzeichen zu puffern, um die Array -Größe zu puffern. */Public Class BufferedWriter erweitert den Schriftsteller {// Basisarray Private Writer Out; // Puffer Array Private char cb []; // nchars-die Gesamtzahl der Zeichen in CB, NextChar-der Index des nächsten Zeichens in CB Private int nchars, NextChar; // Standard -CB -Größe private statische int defaultCharBufferSize = 8192; /*** Zeilenabscheiderzeichenfolge. Dies ist der Wert der Linie.Sesparator * Eigenschaft zu dem Zeitpunkt, in dem der Stream erstellt wurde. * Line Newline -Zeichen, verwendet für die Newline -Methode. Verschiedene Plattformen haben unterschiedliche Werte. */ private String LineseParator; /*** Erstellen Sie den BufferedWriter BW mit der Standard -CB -Größe. */ public bufferedWriter (writer out) {this (out, defaultCharBufferSize); } / ** * erstellen BR und initialisieren Sie verwandte Felder mit der angegebenen CB -Größe * / public bufferedWriter (writer out, int sz) {super (out); if (sz <= 0). this.out = out; cb = new char [sz]; nchars = sz; nextChar = 0; // Erhalten Sie die Darstellung neuer Line unter verschiedenen Plattformen. LineseParator = (String) java.security.accesscontroller.doprivilegged (new sun.security.action.getPropertyAction ("line.separator"); } / ** Erkennen Sie, ob der zugrunde liegende Zeichenausgangsstrom geschlossen ist } /*** Spülen Sie die zwischengespeicherten Zeichen in CB bis zur zugrunde liegenden, aber nicht die Zeichen im zugrunde liegenden heraus. * Und klar CB. */ void flushbuffer () löscht ioException {synchronized (lock) {sichereropen (); if (nextChar == 0) return; out.write (cb, 0, nextChar); NextChar = 0;}} /*** Schreiben Sie ein einzelnes Zeichen auf CB. */ public void write (int c) löscht ioException {synchronized (lock) {sachorOpen (); if (nextChar> = nchars) FlushBuffer (); CB [NextChar ++] = (char) c;}} /** * Unsere eigene kleine min -Methode, um das Laden von Java.lang.math zu vermeiden, wenn wir * aus Dateideskriptoren ausgeführt haben und wir versuchen, eine Stapelspur zu drucken. */ private int min (int a, int b) {if (a <b) return a; return b; } / *** Schreiben Sie eine Zeichenlänge von Len aus dem Index aus dem Einweis in CB* / public void write (char cbuf [], int off, int len). if ((off <0) || (Aus> cbuf.length) || (len <0) || ((aus + len)> cbuf.length) || ((aus + len) <0)) {thrower New IndexoutOfBoundSexception (); } else if (len == 0) {return; } if (len> = nchars) {/* wenn len größer als die Länge von CB ist, dann werden die vorhandenen Zeichen in CB und Zeichen in CBUF direkt geschrieben, anstatt an CB zu schreiben und dann zu schreiben. */flushbuffer (); out.write (cbuf, off, len); return; } int b = off, t = off + len; while (b <t) {int d = min (nchar - nextChar, t - b); System.ArrayCopy (cbuf, b, cb, nextChar, d); b += d; nextchar += d; if (nextChar> = nchars) FlushBuffer (); }}} / *** Schreiben Sie einen Teil einer String in CB* / public void write (String s, int off, int len). int b = off, t = off + len; while (b <t) {int d = min (nchar - NextChar, t - b); }}} /*** Schreiben Sie eine neue Linie. */ public void newline () löscht ioException {write (linesparator); } / *** diesen Stream aktualisieren und gleichzeitig den zugrunde liegenden Strom aktualisieren out.flush ();}} /*** Schließen Sie diesen Stream und veröffentlicht Ressourcen im Zusammenhang mit diesem Stream. */ public void close () löscht ioException {synchronized (lock) {if (out == null) {return; } try {flushbuffer (); } endlich {out.close (); out = null; CB = NULL; }}}}V.
Zwei: BufferedReader
1. Einführung in Klassenfunktionen:
Pufferter Zeicheneingangsstrom, seine Funktion besteht darin, eine Pufferfunktion für den eingehenden zugrunde liegenden Zeicheneingangsstrom bereitzustellen. Es wird die Zeichen im zugrunde liegenden Charaktereingangsstream (IN) in seinen eigenen Puffer (integriertes zwischengespeichertes Zeichen-Array) gelesen, und dann ruft das Programm die Lesemethode des BufferedReader auf, um die Zeichen im Puffer in das Programm zu lesen. Wenn die Charaktere im Puffer gelesen werden, lesen der BufferedReader den nächsten Datenblock von in und in den Puffer, damit das Programm gelesen werden kann, bis die Daten in IN gelesen werden. Die Vorteile davon sind zunächst die Leseeffizienz und zweitens die Anzahl der Verbindungen, um das Speichermedium zu öffnen. Aus detaillierten Gründen erwähnte der unten erwähnte BufferedWriter. Es gibt eine Schlüsselmethode fill (), bei der die Daten jedes Mal, wenn die Daten im Puffer zehnmal schneller gelesen werden, aus dem Puffer aus dem Puffer ausfüllen und die Daten aus der Festplatte lesen! Dies ist eine sehr schreckliche Verbesserung der Effizienz. Gleichzeitig können wir die Puffergröße des BufferedReaders ohne Verbot nicht angeben. Schließlich dauert es lange, bis es einmal gelesen wird. Zweitens ist der Speicherpreis relativ teuer. Was wir tun können, ist zu versuchen, vernünftige Punkte darin zu finden. Im Allgemeinen müssen wir uns darüber keine Sorgen machen und die Standardgröße des Puffers verwenden, um einen BufferedReader zu erstellen.
2. Einführung in die BufferedReader -API:
A: Die Konstruktion der Methode BufferedReader (Reader IN, INT SZ) erstellt einen BufferedReader basierend auf der angegebenen Größe und dem zugrunde liegenden Zeicheneingangsstrom. BR BufferedReader (Reader in) Verwenden Sie die Standardgröße, um den gepufferten Stream des zugrunde liegenden Ausgangsstroms B zu erstellen: Allgemeine Methode void () Schließen Sie diesen Stream und lassen Sie alle Ressourcen frei, die mit dieser Stream -Void -Marke bezogen werden. Markieren Sie die Position dieses Streams zu diesem Zeitpunkt. BOOLEAN -MARKS -MARKS () stellt fest, ob dieser Stream -Stream -Stream -Stream -Stream -Stream -Stream -Stream -Stream -Stream -Stream -Stream -Stream -Stream -Stream -Stream -Stream -Stream -Stream -Stream -Stream -Stream -Stream -Stream -Stream -Stream -Stream -Stream -Stream -Stream -Stream -Stream -Stream -Stream -Stream -Stream -Stream (). Lesen von Zeichen int read () liest ein einzelnes Zeichen und kehrt in einer Ganzzahlrückgabe zurück. Wenn das Ende in IN gelesen wird, gibt es -1 zurück. int read (char [] cbuf, int off, int len) les len -Zeichen in CBUF beginnend mit dem Index Off, Länge Len String Readline () Lesen Sie eine Zeile Long Skip (Long N) Verwerfen n Zeichen in CBUF in CBUF
3. Quellcodeanalyse
Paket com.chy.io.original.code; importieren java.io.ioxception;/*** Zeichenpuffer -CB -Array für den zugrunde liegenden Zeicheneingangsstrom hinzufügen. Effizienz verbessern * @Version 1.1, 13/11/17 * @authorandychen */Public Class BufferedReader erweitert den Leser {private reader in; private char cb []; private int nchars, NextChar; private statische endgültige int ungültig = -2; private statische endgültige int nicht markiert = -1; private int markedChar = nicht markiert; private int lesaHeadlimit = 0; /*Nur gültig, wenn markedChar> 0*// ** Wenn das nächste Zeichen ein Zeilenfeed ist, überspringen Sie es*/ privat boolean suplf = false; / ** Das Skiplf -Flag, wenn die Marke eingestellt wurde*/ privat boolean markedskiplf = false; private static int DefaultCharBufferSize = 8192; private statische int default expectinLinelength = 80; /*** Erstellen Sie einen BufferedReader basierend auf der angegebenen Größe und dem zugrunde liegenden Zeicheneingangsstrom. Br */ public bufferedReader (Leser in, int sz) {super (in); if (sz <= 0) neue IllegalArgumentException ("Puffergröße <= 0"); } / *** Verwenden Sie die Standardgröße, um einen gepufferten Stream des zugrunde liegenden Ausgabestreams zu erstellen. } / ** Erkennen Sie, ob der zugrunde liegende Zeicheneingangsstrom in geschlossen ist } /*** füllen Sie CB aus. */ private void fill () löscht ioException {int dst; if (markedChar <= unmarkiert) {/ *no mark */ dst = 0;} else {/ *markiert */ int delta = nextChar - markedChar; if (delta> = lesaHeadlimit) {/ * Past Read-Ahead Limit: ungültig marke */markedChar = Invalidated; ReadaHeadLimit = 0; DST = 0; } else {if (readaheadlimit <= cb.length) { / * shuffle im aktuellen Puffer * / System.ArrayCopy (CB, markedChar, CB, 0, Delta); markedChar = 0; DST = Delta;} else { / * veröffentlichen Puffer, um die Read-Ahead-Limit zu ermöglichen * / 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; NextChar = dst;}} /*** Lesen Sie ein einzelnes Zeichen und kehren Sie als Ganzzahl zurück. Wenn das Ende in IN gelesen wird, gibt es -1 zurück. */ public int read () löscht ioException {synchronized (lock) {sachorOpen (); für (;;) {if (nextChar> = nchars) {fill (); if (nextChar> = nchars) return -1;} if (sciplf) {sciplf = false; if (cb [nextChar] == '/n') {nextChar ++; Fortsetzung; }} return cb [nextChar ++]; }}} /*** Lesen Sie die Len -Zeichen in CBUF aus der Länge, die aus dem Abschluss aus dem Abschluss ausgeschaltet wird in den lokalen Puffer. Auf diese Weise werden gepufferte Streams harmlos kaskaden. */ if (len> = cb.length && markedChar <= unmarkiert &&! Skiplf) {return in.read (cbuf, off, len); } fill ();} if (nextChar> = nchars) return -1; if (sciplf) {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; } / *** Lesen Sie Len -Zeichen in in CBUF, um Len aus dem Index aus dem Index aus dem Index zu lenken* / public int read (char cbuf [], int off, int len) löst IoException {synchronized (lock) {versichertopen () aus; if ((off <0) || (Aus> cbuf.length) || (len <0) || ((aus + len)> cbuf.length) || ((aus + len) <0)) {thrower New IndexoutOfBoundSexception (); } else if (len == 0) {return 0; } int n = read1 (cbuf, aus, 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;}} / *** Lesen Sie eine Zeile von in In und Ignorore Line Breaks* / String Readline (boolean ignorelf) löscht IOException {StringBuffer s = null; int startChar; synchronisiert (lock) {sachorOpen (); boolean omitlf = ignorelf || 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; / * Überspringen Sie einen übrig gebliebenen '/n', falls erforderlich */if (omitlf && (cb [nextChar] == '/n') NextChar ++; sciplf = false; omitlf = false; Charloop: für (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 (defaultExpectedLinelength); }}} / ** * Lesen Sie eine Zeile von IN, * / public String readline () IOException {return readline (false); } / *** näher in* / public Long Skip (long n) löst ioException {if (n <0l) {neue IllegalArgumentException ("Wert überspringen");} synchronisiert (lock) {versichern (); lang r = n; wob 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;}} / ** * Bestimmen Sie, ob CB leer ist oder ob im zugrunde liegenden in den zugrunde liegenden in. / * * Wenn Newline übersprungen werden muss und der nächste Lesen ein neuer Charakter ist, überspringen Sie sie einfach sofort. */ if (Skiplf) {/ * Beachten Sie, dass in.ready () nur dann true zurückgibt, wenn der nächste * im Stream gelesen wird. */if (nextChar> = nchars && in.ready ()) {fill ();} if (nextChar <nchar) {if (cb [nextChar] == '/n') NextChar ++; sciplf = false;}} return (NextChar <nchars) || in.ready ();}} / *** Bestimmen Sie, ob dieser Stream Markierungen unterstützt* / public boolean marksSupported () {return true; } /*** markieren Sie die Position dieses Streams zu diesem Zeitpunkt und ermöglichen das Lesen von Readaheadlimit -Zeichen, bevor die Methode zur Reset -Methode fehlschlägt. */ public void mark (int readaheadlimit) löst ioException {if (ReadaHeadLimit <0) aus {neue IllegalArgumentException ("Read-Ahead <0");} synchronisiert (lock) {sicherstellen, dass {sacopen (); this.readaheadlimit = Readaheadlimit; markedChar = nextChar; markedskiplf = Skiplf;}} /*** Die Position zurücksetzen, in der in der letzten markiert war. Das heißt, der nächste Charakter wird aus der zuletzt markierten Position gelesen. */ public void reset () löscht ioException {synchronized (lock) {sorgeneopen (); if (markedChar <0) neue IOException werfen (((markedChar == "? NextChar = markedChar; Skiplf = markedskiplf;}} // Schließen Sie diesen Stream und veröffentlichen Sie alle Ressourcen, die sich auf diesen Stream beziehen, public void close () löst ioException {synchronisierte (lock) {if (in == null) return; in.close (); in = null; cb = null;}}}4. Beispieldemonstration:
Paket com.chy.io.original.test; import Java.io.bufufferedReader; Import Java.io.BufferedWriter; Import Java.io.file; Import Java.io.io.fileader; Import Java.io.io.fileWriter; {/*** Der Test dieser beiden Klassen hier ist relativ einfach, nämlich den Dateizeichenstream zu wickeln und das Dateikopieren zu implementieren* Wenn Sie interessiert sind, können Sie die Effizienz testen, faul sein. Datei ("e: //copyoftest.txt"); BufferedReader BR = New BufferedReader (neuer FileReader (resoucefile); BufferedWriter bw = neuer BufferedWriter (neuer FileWriter (TargetFile)); char [] cbuf = new char [1024]; int n = 0; -1) {bw.write (CBUF, 0, n);} // Vergessen Sie nicht, den Fluss zu aktualisieren und zu schließen, andernfalls kann die Ressourcen nicht rechtzeitig freigegeben werden, und andererseits kann es einen Datenverlust verursachen, wenn Br.CLOSE (); bw.flush (); bw.close ();}}}}}}}}}}}}}}}}}}}} freigegeben werden.Zusammenfassen:
Für BufferedReader und BufferedWriter besteht die Essenz darin, dem zugrunde liegenden Zeicheneingang und Ausgangsstrom eine Pufferfunktion hinzuzufügen, zuerst Daten in den zugrunde liegenden Stream in Form einer Gruppe von Lesevorgängen gleichzeitig zu lesen oder zu schreiben und dann auf dem Puffer zu arbeiten. Dies spart nicht nur Effizienz, sondern spart auch Ressourcen. Schließlich sollten diese beiden Klassen im Programm aus Effizienzgründen für Streams auf niedriger Ebene verwendet werden, um sie zu dekorieren, anstatt nur den Stream zu halten und sie direkt hochzuladen, um zu denken, dass sie verwirklicht werden können.