1

このシナリオを考えてみましょう: 私はファイルを読んでいて、各行を少し調整してから、データを新しいファイルに保存しています。今、私はそれを行うために2つの方法を試しました:

  1. データを文字列に格納し、最後に次のようにターゲット ファイルに書き込みます。

            InputStream ips = new FileInputStream(file);
            InputStreamReader ipsr = new InputStreamReader(ips);
            BufferedReader br = new BufferedReader(ipsr);
    
            PrintWriter desFile = new PrintWriter(targetFilePath);
            String data = "";
            while ((line = br.readLine()) != null) {
                if (line.contains("_Stop_"))
                    continue;
                String[] s = line.split(";");
                String newLine = s[2];
                for (int i = 3; i < s.length; i++) {
                    newLine += "," + s[i];
                }
                data+=newLine+"\n";
            }
            desFile.write(data);
            desFile.close();
            br.close();
    
  2. 以下のように、while ループで PrintWriter の println() メソッドを直接使用します。

             while ((line = br.readLine()) != null) {
                if (line.contains("_Stop_"))
                    continue;
                String[] s = line.split(";");
                String newLine = s[2];
                for (int i = 3; i < s.length; i++) {
                    newLine += "," + s[i];
                }
                desFile.println(newLine);
            }
            desFile.close();
            br.close();
    

2 番目のプロセスは、1 番目のプロセスよりもはるかに高速です。さて、私の質問は、これら2つのプロセスで何が起こっているのか、実行時間によって大きく異なるのでしょうか?

4

3 に答える 3

2

文字列に追加すると、次のようになります。

  1. 新しい文字列にメモリを割り当てる
  2. 以前にコピーしたすべてのデータをコピーします。
  3. 新しい文字列からデータをコピーします。

このプロセスを 1 行ごとに繰り返します。つまり、N 行の出力に対して O(N^2) バイトをコピーします。

一方、PrintWriter への書き込みは次のようになります。

  1. データをバッファにコピーします。
  2. ときどきバッファをフラッシュします。

N 行の出力に対して、O(N) バイトだけをコピーすることを意味します。

于 2014-10-24T22:52:35.797 に答える
1

1 つには、+= を使用して追加することにより、非常に多くの新しい String オブジェクトを作成しています。それは間違いなく物事を遅くすると思います。

ループの外で宣言された StringBuilder sb を使用して追加してから、desFile.write(sb.toString()); を呼び出してみてください。そしてそれがどのように機能するかを見てください。

于 2014-10-24T22:49:06.623 に答える
1

まず第一に、2 つのプロセスは同じデータを生成しません。これは、呼び出すプロセスではprintln行間に行区切り文字があるのに対し、すべてのデータをバッファーに構築して一度に書き込むプロセスではそうではないためです。

しかし、パフォーマンスの違いの理由はおそらく、生成して破棄するオブジェクトの膨大な数StringStringBuilder完全なファイルの内容をメモリに保持するために割り当てる必要があるメモリ、およびガベージ コレクタにかかる時間です。

特にループで大量の文字列連結を行う場合は、StringBuilderループの前に a を作成し、それを使用してループ内の結果を蓄積することをお勧めします。

ただし、大きなファイルを処理する場合は、その都度出力を書き出す方がよいでしょう。アプリケーションのメモリ要件は低くなりますが、結果全体をメモリに構築する場合、必要なメモリは出力ファイルのサイズと同じになります。

于 2014-10-24T22:50:08.727 に答える