2012-01-07 12 views
1

以下は私のコードですが、一度に500行以上を処理できません。TextFileの読み込みをより効率的にする(大きいファイルタイプ)

これは、行の末尾にaを追加すると同時に検出する必要があります。私が現在やっているのは、2つの異なるテキストボックスに分割して、コピー貼り付けで必要なものを保存していますが、ファイルが大きすぎるとハングアップするようです。

誰かが効率化を助けることができますか?それは本当に感謝します。

private void button1_Click_1(object sender, EventArgs e) 
    { 
     if (openFileDialog1.ShowDialog() == DialogResult.Cancel) 
      return; 

     System.IO.StreamReader Reader = new System.IO.StreamReader(openFileDialog1.FileName); 

     //Create a filestream 

     FileStream fStr; 

     try 
     { 
      //Set filestream to the result of the pick of the user 

      fStr = new FileStream(openFileDialog1.FileName, FileMode.Open, FileAccess.Read); 


      //Create a streamreader, sr, to read the file 

      StreamReader sr = new StreamReader(fStr); 

      //While the end of the file has not been reached... 

      while (sr.Peek() >= 0) 
      { 
       //Create a 'line' that contains the current line of the textfile 

       string line = sr.ReadLine().ToLower(); 

       if (line.Contains("staff")) 
       { 

        line += ","; //Add a , to the end of the line**Important** 
        textBox1.Text += line + Environment.NewLine; 
        releventcount += 1; 
       } 
       else 
       { 
        line += ","; //Add a , to the end of the line**Important** 
        textBox2.Text += line + Environment.NewLine; 
        irreleventcount += 1; 
       } 

       label1.Text = "Relevent: "; 
       label2.Text = "Irrelevant: "; 
      } 
      //Close the file so other modules can access it 
      sr.Close(); 
      //If something goes wrong, tell the user 
     } 
     catch (Exception) 
     { 

      MessageBox.Show("Error opening file", "Check the CODE ! ~.~"); 
     } 


    } 
+0

[コードレビュー](http://codereview.stackexchange.com)に投稿することを検討してください。 – James

答えて

2

:ここ

は、はるかに効率的であるべき書き直したものです。あなたの現在のコードがやっていることを行うためのいくつかのより簡潔な方法がありますが、読み込み速度を大幅に向上させることはありません。

コードのボトルネックは、文字列を追加することです。 StringBuilderを使用すると良いアドバイスが得られますが、List<string>を作成して最後にstring.Joinを呼び出すと、それ以上の効果が得られます。たとえば、

if (openFileDialog1.ShowDialog() == DialogResult.Cancel) 
    return; 
List<string> staff = new List<string>(); 
List<string> other = new List<string>(); 

foreach (var line in File.ReadLines(openFileDialog1.FileName)) 
{ 
    line = line.ToLower(); 
    if (line.Contains("staff")) 
    { 
     staff.Add(line); 
    } 
    else 
    { 
     other.Add(line); 
    } 
} 

relevantcount = staff.Count; 
irrelevantCount = other.Count; 

textBox1.Text = string.Join(","+Environment.NewLine, staff); 
textBox2.Text = string.Join("."+Environment.NewLine, other); 

また、一度に500行しか処理できないとします。あなたのユーザーインターフェイスに、より多くの情報を処理できないようなものがありますか?確かに、あなたが示したコードには、このような下限を持つものは何もありません。

+0

List とjoinはstringbuilderよりも効率的ですか? stringbuilderを使用すると、.netは文字列をあらかじめ割り当てられたバッファに追加します。質問の制約があれば、割り振る量を正確に決定できます。リストのアプローチでは、行数と同じ数のオブジェクトを管理し、処理する必要があります。私にとっては、.netが文字列を2回処理して保存する方がはるかに効率的です。 –

+0

@competent_tech:どちらが速いのかは分かりませんが、大きな違いがあるとは思えません。 I/O時間が支配的です。私はあなたが 'StringBuilder'のためにどのくらい割り当てるべきかを知っていると言うことができるところはわかりません。あなたはファイルサイズを見ることができますが、再割り当てを避けるためにリスト容量を見積もることもできます。リストがスコープ内にある間にガベージコレクションがトリガされても、あなたが 'StringBuilder'を使っていても処分の問題が存在するならば、いくつかの追加のオーバーヘッドがあるかもしれません。正直言って、私のアプローチは、コードが簡単なので主に好きです。 –

+0

ありがとうございます!私は間違いなくここで何かを学んだ – CodeGuru

1

500行は何もありません。

File.ReadAllLinesとFile.WriteAllLinesを試してください。

次に、メモリ内の文字列の配列に対して作業を行い、反復IOを避けることができます。

1

ファイルを1行ずつ読み込むのは非常に遅いです。大量のデータ(またはあまりにも巨大でない場合はファイル全体)を読むことで、このコードをより高速にすることができます。たとえば、File.ReadAllLinesを使用してファイル全体を別々の行として読み込むか、FileStreamとRead()をバッファに使用し、改行(\ n、\ r)文字を検索して個々の行を探します。

データをエクスポートするには、テキストボックスにコピーして貼り付けないでください。結果を1つまたは2つの新しいファイルに書き込んだ後に開きます。

0

StringBuildersを使用すると、継続的にテキストを追加するよりテキストボックスのテキストを集めるほうがはるかに効率的です。

また、ブロックを使用してさまざまなストリームをラップする必要があります。私はそれはあなたが最終的にここで達成しようとしているのが何であるかわからないんだけど

private void button1_Click_1(object sender, EventArgs e) 
    { 
     if (openFileDialog1.ShowDialog() == DialogResult.Cancel) 
      return; 

     try 
     { 
      //Set filestream to the result of the pick of the user 
      using (var fStr = new FileStream(openFileDialog1.FileName, FileMode.Open, FileAccess.Read)) 
      { 
       //Create a streamreader, sr, to read the file 
       using (var sr = new StreamReader(fStr)) 
       { 
        var sbTextBox1 = new System.Text.StringBuilder(10000); 
        var sbTextBox2 = new System.Text.StringBuilder(10000); 

        //While the end of the file has not been reached... 
        while (sr.Peek() >= 0) 
        { 
         //Create a 'line' that contains the current line of the textfile 
         string line = sr.ReadLine().ToLower(); 

         if (line.Contains("staff")) 
         { 
          //Add a , to the end of the line**Important** 
          sbTextBox1.Append(line).Append(",").AppendLine(); 
          releventcount += 1; 
         } 
         else 
         { 
          //Add a , to the end of the line**Important** 
          sbTextBox2.Append(line).Append(",").AppendLine(); 
          irreleventcount += 1; 
         } 
        } 

        textBox1.Text = sbTextBox1.ToString(); 
        textBox2.Text = sbTextBox2.ToString(); 

        label1.Text = "Relevent: "; 
        label2.Text = "Irrelevant: "; 

        //Close the file so other modules can access it 
        sr.Close(); 
       } 
      } 
     } 
     catch (Exception) 
     { 
      MessageBox.Show("Error opening file", "Check the CODE ! ~.~"); 
     } 
    } 
+0

実際には、あなたが望むのは 'sb.TextBox.Append(line).AppendLine("、 ")'そうでなければ先行するコンマがあります。もちろん、私の場合、末尾にカンマが付きます。 。 。 –

+0

良いキャッチ、ありがとう。私はまた、 'sbTextBox2'の代わりに' sbTextBox1'をelse文で使っていました。どちらも固定されています –

+0

はい、StringBuilderが効率的ですが、この場合は時間の差異に気付かないでしょう。 500は大きな数字ではありません。 –

関連する問題