web-dev-qa-db-ja.com

Java-ファイルからの読み取り。入力ストリームとリーダー

すべてのJava実装でファイルからの読み取りを見ると、ほとんどの場合、ファイルリーダーが行ごとに読み取られるのがわかります。システムが必要なため、これは非常に非効率的だと思います行ごとに呼び出します。

代わりに私がやっていたことは、入力ストリームを使用してバイトを直接取得することです。私の実験では、これはかなり高速です。私のテストは1MBのファイルでした。

    //Stream method
    try {
        Long startTime = new Date().getTime();

        InputStream is = new FileInputStream("test");
        byte[] b = new byte[is.available()];
        is.read(b);
        String text = new String(b);
        //System.out.println(text);

        Long endTime = new Date().getTime();
        System.out.println("Text length: " + text.length() + ", Total time: " + (endTime - startTime));

    }
    catch (Exception e) {
        e.printStackTrace();
    }

    //Reader method
    try {
        Long startTime = new Date().getTime();

        BufferedReader br = new BufferedReader(new FileReader("test"));
        String line = null;
        StringBuilder sb = new StringBuilder();
        while ((line = br.readLine()) != null) {
            sb.append(line);
            sb.append("\n");
        }
        String text = sb.toString();

        Long endTime = new Date().getTime();
        System.out.println("Text length: " + text.length() + ", Total time: " + (endTime - startTime));

    }
    catch (Exception e) {
        e.printStackTrace();
    }

これにより、次の結果が得られます。

Text length: 1054631, Total time: 9
Text length: 1034099, Total time: 22

では、なぜ人々はストリームの代わりにリーダーを使うのでしょうか?

テキストファイルを受け取り、すべてのテキストを含む文字列を返すメソッドがある場合、ストリームを使用して行う方が良いでしょうか。

14
Jeremy

リンゴとバナナを比較しています。一度に1行ずつ読み取ることは、bufferedReaderを使用しても、データをできるだけ速く取得するよりも効率が悪くなります。 availableの使用は、すべての状況で正確であるとは限らないため、お勧めしません。暗号ストリームを使い始めたとき、私はこれを自分で見つけました。

9
ControlAltDel

BufferedReaderバッファーサイズを増やしてみてください。例えば:

_BufferedReader br = new BufferedReader(new FileReader("test"),2000000);
_

適切なバッファサイズを選択すると、より高速になります。

次に、Readerを使用したサンプルで、StringBuilderへの入力に時間を費やします。行を処理する必要がある場合は、ファイルを1行ずつ読み取る必要があります。しかし、文字列内のテキストを読み取るだけでよい場合は、public int read(char[] cbuf)を使用してより大きなテキストチャンクを読み取り、適切なサイズで初期化されたStringWriterにチャンクを書き込みます。

InputStreamを選択するか、Readerはパフォーマンスに依存しません。リーダーを使用すると文字セットをより簡単に処理できるため、通常はテキストデータを読み取るときにReaderを使用します。

別のポイント、ここにあなたのコード

_byte[] b = new byte[is.available()];
is.read(b);
String text = new String(b);
_

それは正しくありません。 documentation

InputStreamの一部の実装はストリーム内の合計バイト数を返しますが、多くはそうではないことに注意してください。このメソッドの戻り値を使用して、このストリームのすべてのデータを保持することを目的としたバッファーを割り当てることは決して正しくありません。

注意してください、修正する必要があります。

3
dash1e

FileReaderは通常、BufferedReaderと組み合わせて使用​​されます。特に、ファイルに明確に定義されたレコード構造があり、各レコードが1行に対応している場合は、ファイルを1行ずつ読み取ることがよくあるためです。

また、FileReaderを使用すると、 javadocs で説明されているように、文字エンコードと変換を処理するための作業の一部を簡略化できます。

文字ファイルを読み取るためのコンビニエンスクラス。このクラスのコンストラクタは、デフォルトの文字エンコーディングとデフォルトのバイトバッファサイズが適切であると想定しています。FileReaderは、文字のストリームを読み取るためのものです。

3
Óscar López