web-dev-qa-db-ja.com

InputStreamまたはInputStreamReaderをバッファリングする必要がありますか?

次の2つのバッファリングアプローチの違い(ある場合)は何ですか?

Reader r1 = new BufferedReader(new InputStreamReader(in, "UTF-8"), bufferSize);
Reader r2 = new InputStreamReader(new BufferedInputStream(in, bufferSize), "UTF-8");
27
bdkosher

r1の方が効率的です。 InputStreamReader自体には大きなバッファはありません。 BufferedReaderは、InputStreamReaderよりも大きなバッファーを持つように設定できます。 r2InputStreamReaderは、ボトルネックとして機能します。

簡単に言えば、ボトルではなく漏斗からデータを読み取る必要があります。


更新:ここに小さなベンチマークプログラムがあります。コピーして貼り付けて実行します。ファイルを準備する必要はありません。

package com.stackoverflow.q3459127;

import Java.io.BufferedInputStream;
import Java.io.BufferedReader;
import Java.io.BufferedWriter;
import Java.io.File;
import Java.io.FileInputStream;
import Java.io.FileWriter;
import Java.io.IOException;
import Java.io.InputStreamReader;
import Java.io.Reader;

public class Test {

    public static void main(String... args) throws Exception {

        // Init.
        int bufferSize = 10240; // 10KB.
        int fileSize = 100 * 1024 * 1024; // 100MB.
        File file = new File("/temp.txt");

        // Create file (it's also a good JVM warmup).
        System.out.print("Creating file .. ");
        BufferedWriter writer = null;
        try {
            writer = new BufferedWriter(new FileWriter(file));
            for (int i = 0; i < fileSize; i++) {
                writer.write("0");
            }
            System.out.printf("finished, file size: %d MB.%n", file.length() / 1024 / 1024);
        } finally {
            if (writer != null) try { writer.close(); } catch (IOException ignore) {}
        }

        // Read through funnel.
        System.out.print("Reading through funnel .. ");
        Reader r1 = null;        
        try {
            r1 = new BufferedReader(new InputStreamReader(new FileInputStream(file), "UTF-8"), bufferSize);
            long st = System.nanoTime();
            for (int data; (data = r1.read()) > -1;);
            long et = System.nanoTime();
            System.out.printf("finished in %d ms.%n", (et - st) / 1000000);
        } finally {
            if (r1 != null) try { r1.close(); } catch (IOException ignore) {}
        }

        // Read through bottle.
        System.out.print("Reading through bottle .. ");
        Reader r2 = null;        
        try {
            r2 = new InputStreamReader(new BufferedInputStream(new FileInputStream(file), bufferSize), "UTF-8");
            long st = System.nanoTime();
            for (int data; (data = r2.read()) > -1;);
            long et = System.nanoTime();
            System.out.printf("finished in %d ms.%n", (et - st) / 1000000);
        } finally {
            if (r2 != null) try { r2.close(); } catch (IOException ignore) {}
        }

        // Cleanup.
        if (!file.delete()) System.err.printf("Oops, failed to delete %s. Cleanup yourself.%n", file.getAbsolutePath());
    }

}

Latitude E5500での結果 Seagate Momentus 7200. ハードディスク:

ファイルの作成..完了、ファイルサイズ:99 MB。
漏斗からの読み取り.. 1593ミリ秒で完了。 。]
28
BalusC

BufferedReaderreadLineメソッドをサポートするため、r1はラインベースのストリームを読み取るときにも便利です。 char配列バッファーまたはcharsにコンテンツを1つずつ読み込む必要はありません。ただし、r1BufferedReaderにキャストするか、変数にその型を明示的に使用する必要があります。

私はこのコードスニペットをよく使用します。

BufferedReader br = ...
String line;
while((line=br.readLine())!=null) {
  //process line
}
5
pcjuzer

FWIW、ファイルをJava 8で開く場合は、 Files。 newBufferedReader(Path) 。ここで説明する他のソリューションとパフォーマンスを比較する方法はわかりませんが、少なくとも、どの構成をJDKにバッファリングするかを決定することになります。

1
Max