2013-04-24 2 views
6

私は何千もの動的に生成された行をテキストファイルに書き込む必要があります。 私には2つの選択肢があります。どちらは少ないリソースを消費し、他のものよりも速いのですか?何が少ないリソースを消費し、File.AppendTextまたはFile.WriteAllTextがStringBuilderに最初に格納されていますか?

のStringBuilderとFile.WriteAllTextを使用したA.

StringBuilder sb = new StringBuilder(); 
foreach(Data dataItem in Datas) 
{ 
sb.AppendLine(String.Format("{0}, {1}-{2}",dataItem .Property1,dataItem .Property2,dataItem .Property3)); 
} 
File.WriteAllText("C:\\example.txt", sb.ToString(), new UTF8Encoding(false)); 

B. File.AppendText

using(StreamWriter sw = File.AppendText("C:\\example.txt")){ 
           foreach (Data dataItem in Datas) 
           { 
            sw.WriteLine(String.Format("{0}, {1}-{2}",dataItem .Property1,dataItem .Property2,dataItem .Property3)); 
           } 
          } 
+5

http://ericlippert.com/2012/12/17/performance-rant/ –

+0

ネットワーキングとデータベース書き込みが関係するため、できるだけ早くこの操作を行う必要があります。そして私はいくつかのボトルネックに関連しているので、私はあなたがリンクした記事を知らないので、私は必要なので、この質問をしています。 –

+1

スピードがあなたの主な関心事であるかどうかはわかりません。メモリ使用量は明らかにあなたの意思決定を促進するはずです。データが常に小さい場合は、いくつかのテストを実行してどちらが速いかを判断できます。 – juharr

答えて

14

最初のバージョンでは、すべてをStringBuilderに入れ、書き込みを行うと、ほとんどのメモリが消費されます。テキストが非常に大きい場合、メモリが不足する可能性があります。それはより速くなる可能性がありますが、遅くなる可能性もあります。

2番目のオプションでは、メモリの使用量が大幅に少なくなります(基本的にはStreamWriterバッファのみ)、非常にうまく動作します。私はこのオプションをお勧めします。最初の方法よりも優れている可能性があり、メモリ不足の可能性はありません。

出力バッファのサイズを大きくすることで、速度をかなり向上させることができます。むしろより

File.AppendText("filename") 

がでストリームを作成します。

const int BufferSize = 65536; // 64 Kilobytes 
StreamWriter sw = new StreamWriter("filename", true, Encoding.UTF8, BufferSize); 

64Kのバッファサイズはデフォルトの4Kバッファサイズよりもはるかに優れた性能を提供します。あなたはもっと大きくすることができますが、私は64Kより大きいほうが性能の向上が少なく、実際にはのパフォーマンスがの性能を得ることができることが分かりました。

+0

このバッファサイズは予想するのが難しいです。これは、必要な行とデータの量がわからないためです。私は2kと4kの間で考える。私はOutOfMemoryExceptionのリスクを抱えていました。私が恣意的にBuffizeizeを選択すると、必要なものよりも小さなものが選択されます。 –

+0

@AlbertoLeón:いいえ、あまりにも小さなバッファサイズを選んでも、メモリ不足例外は発生しません。それは 'StreamWriter'がすべての文字に対してWindowsの' Write'関数を呼び出さなくて済むようにするために使う一時バッファです。データをバッファした後、ブロックに書き込みます。バッファより大きいブロックを書き込もうとすると、エラーは発生しません。 –

+0

素晴らしい!あなたのソリューションは私の2番目の改善をもたらしたと思います。私はそれが好きです。 –

7

を使用してあなたはFile.AppendAllLines()

を使用して、少なくとも一つの他の選択肢を持っています
var data = from item in Datas 
      select string.Format("{0}, {1}-{2}", item.Property1, item.Property2, item.Property3); 

File.AppendAllLines("Filename", data, new UTF8Encoding(false)); 

理論的には、一度に1行しかメモリにバッファリングされないため、最初のアプローチよりも少ないメモリしか使用しません。

おそらく2番目のアプローチとほぼ同じです。私はあなたに第三の選択肢を示しています。この方法の唯一の利点は、Linqシーケンスをフィードすることができることです。

あなたはjuharrは、上記のように、メモリ使用量を最小限に抑えることに集中しなければならないので、I/O速度は、他の考慮事項を矮星します(もちろん、また、時期尚早な最適化の危険性を考慮!)あなたの第二手段を用いてその

アプローチ、または私がここに入れたものです。

+0

私はこれが一番好きだと思います。いい答えだ。 –

+0

私はラインの数が減ったので驚いた。もっと読みやすいです。しかし、varデータとは何ですか?文字列の配列ですか? –

+0

@ AlbertoLeon: 'data'は' IEnumerable 'です。その結果を理解するために、LINQを読む必要があります。 –

関連する問題