[JAVA] Zusammenfassung von FileInputStream und BufferedInputStream

Überblick

Ich habe irgendwo zuvor einen Artikel gefunden, in dem das Setzen von FileInputStream auf BufferedStream den Prozess beschleunigt. Also werde ich dieses Mal einen Artikel über FileInputStream und BufferedInputStream schreiben.

Postskriptum 2019/10/06 In dem Kommentar erklärte er, warum die Verarbeitungsgeschwindigkeit auch mit FileInputStream erhöht wird, wenn InputStreamReader verwendet wird. Bitte nehmen Sie Bezug darauf.

Was ist der Unterschied zwischen den beiden?

Der Unterschied zwischen den beiden war leicht zu verstehen, wenn man das Folgende liest.

Dies ist ein nativer Aufruf an das Betriebssystem, das die Festplatte zum Lesen von 1 Byte verwendet. Dies ist eine schwere Operation.

Mit> BufferedInputStream delegiert diese Methode an eine überladene read () -Methode, die 8192 Bytes liest und sie bis zur Verwendung puffert. Es wird nur noch 1 Byte zurückgegeben (obwohl die anderen Bytes reserviert sind). Auf diese Weise liest BufferedInputStream aus der Datei mit weniger nativen Aufrufen des Betriebssystems.

Warum mit BufferedInputStream Dateien in Bytes schneller lesen als mit FileInputStream?

Mit anderen Worten, FileInputStream liest jeweils nur ein Byte, was viel Festplattenzugriff verursacht, während BufferedInputStream eine große Anzahl von Bytes gleichzeitig liest, sodass Daten mit weniger Festplattenzugriff gelesen werden können. ist.

Die Ergebnisse des tatsächlichen Experiments sind wie folgt. Erstellen Sie zunächst eine Datei, die wie folgt gelesen werden soll.

Lesen Sie die erstellte Datei wie folgt



final FileOutputStream fos = new FileOutputStream(filePath);
final BufferedOutputStream bos = new BufferedOutputStream(fos);
final OutputStreamWriter osw = new OutputStreamWriter(bos, Charset.defaultCharset());
final PrintWriter pr = new PrintWriter(osw);
for (int i = 0; i < 500000; i++) {
    pr.println("Ah");
}
pr.close();

Nachdem ich die obige Datei mit FileInputStream als Prozess 1 gelesen hatte, habe ich den Lesevorgang an StringBuilder angehängt.

Prozess 1_FileInputStream


//FileInputStream
StringBuilder sb = new StringBuilder();
final FileInputStream inputStream = new FileInputStream(filePath);

//wird bearbeitet
long startTime = System.currentTimeMillis();
int line;
while (true) {
    line = inputStream.read();
    if (line == -1) {
        break;
    }
    sb.append(line);
}
long endTime = System.currentTimeMillis();
System.out.println("Verarbeitungszeit: " + (endTime - startTime));
inputStream.close();

In Prozess 2 wurde FileInputStream in BufferedInputStream eingeschlossen und verwendet.

Prozess 2_BufferedInputStream


//BufferedInputStream
StringBuilder sb = new StringBuilder();
final FileInputStream fis = new FileInputStream(filePath);
BufferedInputStream inputStream = new BufferedInputStream(fis);

//wird bearbeitet
long startTime = System.currentTimeMillis();
int line;
while (true) {
    line = inputStream.read();
    if (line == -1) {
        break;
    }
    sb.append(line);
}
long endTime = System.currentTimeMillis();
System.out.println("Verarbeitungszeit: " + (endTime - startTime));
inputStream.close();
fis.close();

Das Ergebnis ist wie folgt (Einheit ist ms). FileInputStream Erstes Mal: 3840 Zweites Mal: 3820 Drittes Mal: 3772

BufferedInputStream

  1. Mal: 109 Zweites Mal: 111 Drittes Mal: 117

Es ist auf einen Blick offensichtlich. Offensichtlich ist BufferedInputStream schneller. Übrigens, als die Anzahl der For-Anweisungen auf 50 festgelegt wurde, waren es 2761196 ns für FileInputStream und 2198539 ns für BufferedInputStream, die sich nicht wesentlich unterscheiden.

Gibt es einen Unterschied, wenn ich InputStreamReader verwende?

Die InputStreamReader-Klasse wird verwendet, um die Byte-Zeichenfolge der gelesenen Datei in Zeichen zu konvertieren. Tatsächlich stellte sich jedoch heraus, dass der Unterschied zwischen FileInputStream und BufferedInputStream durch die Verwendung von InputStreamReader nahezu beseitigt wird.

Prozess 3_FileInputStream+InputStreamReader


//FileInputStream + InputStreamReader
StringBuilder sb = new StringBuilder();
final FileInputStream inputStream = new FileInputStream(filePath);
final InputStreamReader reader = new InputStreamReader(inputStream);

//wird bearbeitet
long startTime = System.currentTimeMillis();
int line;
while (true) {
    line = reader.read();
    if (line == -1) {
        break;
    }
    sb.append(line);
}
long endTime = System.currentTimeMillis();
System.out.println("Verarbeitungszeit: " + (endTime - startTime));
inputStream.close();
reader.close();

Prozess 4_BufferdInputStream+InputStreamReader


//BufferdInputStream + InputStreamReader
StringBuilder sb = new StringBuilder();
final FileInputStream inputStream = new FileInputStream(filePath);
final BufferedInputStream bufferedInputStream = new BufferedInputStream(inputStream);
final InputStreamReader reader = new InputStreamReader(bufferedInputStream);

//wird bearbeitet
long startTime = System.currentTimeMillis();
int line;
while (true) {
    line = reader.read();
    if (line == -1) {
        break;
    }
    sb.append(line);
}
long endTime = System.currentTimeMillis();
System.out.println("Verarbeitungszeit: " + (endTime - startTime));
inputStream.close();
reader.close();

Das Ergebnis ist wie folgt (Einheit ist ms). FileInputStream + InputStreamReader Erstes Mal: 114 Zweites Mal: 131 Drittes Mal: 154

BufferedInputStream + InputStreamReader Erstes Mal: 163 Zweites Mal: 167 Drittes Mal: 150

Vielleicht, weil es Zeit gibt, eine Instanz von BufferedInputStream zu erstellen, wenn man nur die Ergebnisse betrachtet, scheint es schneller zu sein, die Datei zu lesen, ohne den FileInputStream zu umbrechen, wenn man den InputStreamReader verwendet.

Wenn Sie die gelesene Datei als Zeichenfolge an StringBuilder usw. ausgeben möchten, verwenden Sie wahrscheinlich InputStreamReader. Dies bedeutet, dass zwischen FileInputStream und BufferedInputStream kein großer Unterschied besteht. Im Folgenden finden Sie eine Beschreibung des InputStreamReader.

Was ist InputStreamReader: JavaA2Z

Sollte ich also immer BufferedInputStream verwenden?

Natürlich ist BufferedInputStream schneller, sodass Sie vielleicht denken, dass es besser ist, es zu verwenden, aber es gibt Fälle, in denen die Verwendung nicht sehr effektiv ist.

In diesem Fall wird die Puffergröße im Argument der Lesemethode festgelegt. In InputStream kann die Puffergröße als Argument von read () festgelegt werden, und es ist möglich, die Anzahl der gleichzeitig gelesenen Bytes zu steuern. Wenn nichts festgelegt ist, wird jeweils ein Byte gelesen (mit Ausnahme von BufferedInputStream).

Wenn Sie beispielsweise den Code von Prozess 1 und Prozess 2 wie folgt umschreiben, ändert sich an der Geschwindigkeit nicht viel.

Lesen Sie Prozess 1()Versuchen Sie, die Puffergröße in anzugeben



//Prozess 1 FileInputStream
StringBuilder sb = new StringBuilder();
final FileInputStream inputStream = new FileInputStream(filePath);
// BufferedInputStream bufferedInputStream = new BufferedInputStream(inputStream);
long startTime = System.currentTimeMillis();
int line;
while (true) {
    line = inputStream.read(new byte[8192]);
    if (line == -1) {
        break;
    }
    sb.append(line);
}
long endTime = System.currentTimeMillis();
System.out.println("Verarbeitungszeit: " + (endTime - startTime));
inputStream.close();

Wenn die Verarbeitung sowohl mit FileInputStream als auch mit BufferedInputStream als gelesen (neues Byte [8192]) durchgeführt wurde, betrug die Ausführungszeit für beide 3 ms, und infolgedessen änderte sich die Geschwindigkeit nicht wesentlich.

Ich werde dies zitieren, da die Beschreibung auf der folgenden Website hilfreich war.

Es ist sinnvoll, wenn Sie wahrscheinlich eine große Anzahl kleiner Lesevorgänge (ein oder mehrere Bytes gleichzeitig) ausführen oder die hohe Funktionalität der Buffer-API nutzen möchten. Zum Beispiel die Methode BufferedReader.readLine ().

Wenn Sie jedoch die Methoden read (byte []) oder read (byte [], int, int) verwenden, um nur große Blöcke zu lesen, hat das Umschließen des InputStream mit einem BufferedInputStream keine Auswirkung.

Java - Sollte ich den InputStream immer als BufferedInputStream verpacken

Danach ist, wie oben erwähnt, der Effekt des Umbruchs gering, selbst wenn die Größe der Eingabedatei extrem klein ist, da sich die Geschwindigkeit nicht wesentlich ändert, unabhängig davon, welche verwendet wird.

Zusammenfassung

Bevor ich diesen Artikel schrieb, dachte ich, dass BufferedInputStream absolut schneller als FileInputStream sein würde, aber als ich InputStreamReader (BufferedInputSteramReader) verwendete, stellte ich fest, dass die beiden nicht so unterschiedlich sind.

Ich habe auch erfahren, dass es einige Fälle gibt, in denen die Verwendung von BufferedInputStream nicht sehr effektiv ist.

Wie bei jeder Klasse scheint es wichtig, für jeden Anlass die richtige Klasse zu wählen.

Andere Referenz: Testen Sie die Leistung von BufferedInputStream Stellen Sie beim Einlesen von Daten in ein Array mit FIO10-J. Read () sicher, dass das Einlesen in das Array wie beabsichtigt erfolgt ist /fio10-j.html)

Recommended Posts

Zusammenfassung von FileInputStream und BufferedInputStream
Eine kurze Zusammenfassung der DI- und DI-Container
Zusammenfassung der Hashes und Symbole in Ruby
Zusammenfassung von Java Math.random und Import (Kalender)
[Java] Persönliche Zusammenfassung der Klassen und Methoden (grundlegend)
Zusammenfassung der japanischen Zeiteinstellung und Anzeigemethode
Zusammenfassung der OpenJDK-Quellen
JAR-Datei Übersicht
Zusammenfassung zur Informationssicherheit
Zusammenfassung der Verwendung von FragmentArgs
Zusammenfassung der Verwendung von DBFlow
Zusammenfassung der Java-Unterstützung 2018
Zusammenfassung der häufig verwendeten Befehle in Rails und Docker
Zusammenfassung des ToString-Verhaltens mit Java- und Groovy-Annotationen
Einrichten von JMeter und jEnv
Hintergrund und Mechanismus des Stoffladers
[Java11] Stream-Zusammenfassung - Vorteile von Stream -
Zusammenfassung der Verwendung von ButterKnife
[Java] Zusammenfassung der regulären Ausdrücke
Kombination von Suche und jedem_mit_Index
[Java] Zusammenfassung der Operatoren (Operator)
Urteil von JSONArray und JSONObject
Zusammenfassung der "abstrakten Schnittstellenunterschiede"
Zusammenfassung der Grundlagen der Java-Sprache
Zusammenfassung der Java Math Klasse
Rest- und Leistungstreiber (冪 Leistung)
Vor- und Nachteile von Java
Zusammenfassung der Grundfunktionen von ImageJ
[Java] Zusammenfassung der Steuerungssyntax
Zusammenfassung der Java-Fehlerverarbeitung
[Java] Zusammenfassung der Entwurfsmuster
[Java] Zusammenfassung der mathematischen Operationen
[Webpacker] Zusammenfassung der Installation von Bootstrap und jQuery in Rails 6.0
Zusammenfassung der Probleme und Gegenmaßnahmen beim Betrieb des IE mit WebDriver of Selenium2
Grundlagen der bedingten Verzweigung und Rückkehr
[Für Anfänger] Zusammenfassung des Java-Konstruktors
Java-Veröffentlichungsdatum und EOL-Zusammenfassung
Über Biocontainer fastqc und Java
Zusammenfassung des Pakets [Java Silver Study]
[Rails] Zusammenfassung der komplizierten Routing-Konfiguration
Verwenden Sie redirect_to und rendern Sie richtig
Zusammenfassung des Anfangszustands der Gerätesteuerung
Dies und das von JDK
Zusammenfassung häufig verwendeter Docker-Befehle
[Swift] Vor- und Nachteile von Storyboard
Ordnungsgemäße Verwendung von Mockito und PowerMock
[Rails] Unterschiede und Verwendung von each_with_index und each.with_index
Informationen zu removeAll und RetainAll von ArrayList
Standardimplementierung von Object.equals () und Object.hashCode ()
Anwendung von Downcase- und Slice-Methoden
Zusammenfassung der objektorientierten Programmierung mit Java
Dies und das der ausschließlichen Kontrolle