0

後で解析するファイルを読み込んでいます。ファイルのサイズが 1 MB を超える可能性は低いため、この段階では、これはおそらく重要な問題ではありません。しかし、ベスト プラクティスの理由から、操作を実行するのに最適な時期を知りたいのです。

例:

http://www.dzone.com/snippets/java-read-file-stringから貼り付けたメソッドを使用して、バッファを文字列に読み込んでいます。すべての空白を削除したいと思います。私の方法は現在これです:

private String listRaw;

public boolean readList(String filePath) throws java.io.IOException {
    StringBuffer fileData = new StringBuffer(1024);
    BufferedReader reader = new BufferedReader(
            new FileReader(filePath));
    char[] buf = new char[1024];
    int numRead=0;
    while((numRead=reader.read(buf)) != -1){
        String readData = String.valueOf(buf, 0, numRead);
        fileData.append(readData);
        buf = new char[1024];
    }
    reader.close();
    listRaw = fileData.toString().replaceAll("\\s","");
    return true;
}

そのため、文字列全体をクラス変数に格納するときに、文字列からすべての空白を削除します。

私にとって、これは処理が少なくて済みますが、メモリ使用量が増えていることを意味します。ベスト プラクティスの理由から変数を追加するときにreplaceAll()、変数に操作を適用したほうがよいでしょうか? より多くの処理を使用しますが、余分な空白を渡すことは避けます。readDatafileData

これは、私が取り組んでいるような小さなファイルにはほとんど影響を与えないと思いますが、200MB のログ ファイルの場合はどうなるでしょうか?

それは完全に大文字と小文字に依存しますか、それとも私が従うほうがよいコンセンサスがありますか?


皆さん、ご意見ありがとうございます。Java を書くための正しい方向に私の考え方を向けるのにあなたが役立ったと確信しています。

提起されたポイントを考慮してコードを更新しました。ある時点で、私はスペースを保持したいかもしれないというドン・ロビーの提案を含めて. うまくいけば、物事は今よりよく読めます!

private String listRaw;

public boolean readList(String filePath) throws java.io.IOException {
    StringBuilder fileData = new StringBuilder(51200);
    BufferedReader reader = new BufferedReader(new FileReader(filePath));
    char[] buf = new char[51200];
    boolean spaced = false;
    while(reader.read(buf) != -1){
        for(int i=0;i<buf.length;i++) {
            char c = buf[i];
            if (c != '\t' && c != '\r' && c != '\n') {
                if (c == ' ') {
                    if (spaced) {
                        continue;
                    }
                    spaced = true;
                } else {
                    spaced = false;
                }

                fileData.append(c);
            }
        }
    }
    reader.close();
    listRaw = fileData.toString().trim();
    return true;
}
4

3 に答える 3

7

最後に、正規表現の置換を一度だけ作成して適用することをお勧めします。しかし、あなたはより多くを得るでしょう

  • 妥当なサイズで StringBuilder を初期化する
  • ループ内での文字列の作成を回避し、読み取った文字を StringBuilder に直接追加します
  • 反復ごとに、新しい char バッファーのインスタンス化を無料で回避します。

不必要に長い一時的な String の作成を避けるために、char を char ごとに読み取り、それが whitespaceでない場合にのみ char を StringBuilder に追加することができます。replaceAll()最終的に、StringBuilder には適切な文字のみが含まれ、呼び出しは必要ありません。

于 2012-07-28T17:20:31.290 に答える
4

このコードには実際にはいくつかの非常に非効率な点があり、あなたが提起した比較的重要でない問題について心配する前に、それらを修正する必要があります。

bufまず、ループの反復ごとに新しいオブジェクトを作成しないでください。同じオブジェクトを使用してください。そうすることに問題はありません。新しいデータが古いデータを上書きし、オブジェクトの割り当てを節約できます (これは、実行できる最も高価な操作の 1 つです)。

String次に、同様に、呼び出し先を作成しないでください。配列とオフセット (この場合は 0) と長さ (この場合は )を取るappend()の形式を使用します。ここでも、ループの反復ごとに作成するオブジェクトが 1 つ少なくなります。 .appendcharnumRead

最後に、あなたが実際に尋ねた質問に来てください: ループでそれを行うと、反復ごとに String オブジェクトが作成されますが、今行った調整では、反復ごとにゼロのオブジェクトが作成されます。つまり、ループの終わりが明確な勝者です!

于 2012-07-28T17:18:18.240 に答える
1

実行する解析によっては、別のステップでスペースをまったく削除せず、解析中にそれらを無視する方がよい場合があります。

また、すべての空白を削除したいこともかなりまれです。複数のスペースを単一のスペースに置き換えたくないですか?

于 2012-07-28T17:24:41.683 に答える