0
    read_data = new BufferedReader( new FileReader(args[0]) );
    data_buffer = new StringBuffer();

    int i;

    while(read_data.ready())
    {           
        while((i = read_data.read()) != -1)
        {
            data_buffer.append((char)i);
        }           
    }

    data_buffer.append(System.getProperty("line.separator"));

私がやろうとしているのは、.txt ファイル全体を文字列に読み取り、文字列に改行を追加することです。そして、data_buffer.toString() を渡して新しい Scanner を作成し、後でこの文字列を処理できるようにします。明らかに、非常に大きなファイルでは、このプロセスに多くの時間がかかります。メモリに読み込んだ .txt ファイルに改行を追加するだけです。

アイデア全体が少しハックまたは奇妙に思えることは承知していますが、より迅速な方法はありますか?

乾杯 :)

4

3 に答える 3

3

何かを行うための最速の方法は、多くの場合、まったく行わないことです。

最後の改行が不要になるように構文解析コードを変更してみませんか? 毎回追加する場合は、実際には存在しないのに、存在するかのように動作するようにコードを変更することもできます。

次に試みることは、巨大な String char を char ごとに作成しないようにすることです。これは実際にはかなりコストがかかるためです。Scannerに基づいて を作成できます。これは、データを に読み取ってそれを解析InputStreamするよりもおそらくはるかに高速です。Stringファイルの最後に仮想改行文字を返すように上書きしてFileInputStream、貼り付けられた文字列の挿入を回避できます。

また、絶対にデータをバッファに読み込む必要がある場合は、ストリームの配列ベースのメソッドを使用してバイト配列に読み込む方がよいでしょうread()。バイトごとよりもはるかに高速です。ファイルのサイズを事前に知ることができるので、追加の行末マーカー用のスペースをバッファーに割り当てて、それを配列に挿入することができます。StringBufferを作成してそれから を作成するのとは対照的にString、これはバッファの完全なコピーを必要としません。

于 2012-04-22T14:41:14.267 に答える
2

私が言えることから、あなたが実際にやろうとしていることは、最後の行の終わりに常に行区切り文字があるように見える方法でファイルを読み取ることです。

その場合は、のサブタイプを実装することでこれを行うことができ、FilterReader必要に応じて、文字ストリームの最後に到達したときに追加の文字を1つまたは2つ「挿入」します。

これを行うためのコードは簡単ではありませんが、ファイル全体をメモリにバッファリングする時間とスペースのオーバーヘッドを回避できます。

于 2012-04-22T14:54:27.697 に答える
1

結果のファイルを Scanner に渡すだけの場合は、そのファイルの Readable を作成し、それを Scanner に送信する必要があります。

以下に例を示します (未テスト)。

public class NLReader implements Readable {

    Reader r;
    boolean atEndOfReader = false;
    boolean atEnd = false;

    public NLReader(Reader r) {
        this.r = r;
    }

    public int read(CharBuffer cb) throws IOException {
        if (!atEndOfReader) {
            int result = r.read(cb);
            if (result == -1) {
                atEndOfReader = true;
            } else {
                return result;
            }
        }
        if (!atEnd) {
            String nl = System.getProperty("line.separator");
            cb.append(nl);
            atEnd = true;
            return nl.length();
        }

        return -1;
    }
}

これはファイルを 1 回だけ読み取り、コピーすることはありません (StringBuffer とは異なり、StringBuffer の同期が本当に必要でない限り、代わりに StringBuilder を使用する必要があります)。

また、これは実際のファイルをメモリにロードしないため、メモリの負荷も節約できます。

于 2012-04-22T14:51:02.987 に答える