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.
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
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.
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
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.
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