2017-01-10 3 views
-3
私はFile.ReadLinesメソッドを使用してファイルをロードしています

は、私がアクセスする必要IEnumerableを<T> File.ReadLines()でアクセス回線のパフォーマンスを改善する方法

(ファイルが非常に大きく得ることができるので、私はむしろReadAllLinesよりも、これを使用しました)それぞれの行とそれに対するアクションを実行します。だから私のコードは、この

IEnumerable<String> lines = File.ReadLines("c:\myfile.txt", new UTF8Encoding()); 

StringBuilder sb = new StringBuilder(); 

int totalLines = lines.Count(); //used for progress calculation 

//use for instead of foreach here - easier to know the line I'm on for progress percent complete calculation 
for(int i = 0; i < totalLines; i++){ 

    //for example get the line and do something 
    sb.Append(lines.ElementAt(i) + "\r\n"); 

    //get the line again using ElementAt(i) and do something else 
    //...ElementAt(I)... 
} 

ようなもので、それは、位置iに取得するために全体IEmumerableを反復する必要があるため、だから私のボトルネックは、私はElementAt(i)にアクセスするたびにあります。

File.ReadLinesを引き続き使用する方法はありますか?

EDIT - 私が最初に数える理由は、ユーザーに表示するための進捗状況を計算することができるためです。だから、私はそのためにforeachを削除したのです。

+0

あなたは単にそれを列挙することはできません...? 'foreach(行内のvar行){...}' – pinkfloydx33

+0

'File.ReadLines'のドキュメントを見ましたか? – Servy

+1

本当にカウントが必要ですか?そうしないと、実際には 'Count()'と* then * iteratingを呼び出さないようにする必要があります。 –

答えて

0

あなたが戻って、そのインデックスを経由して行を参照する必要はありませんので、あなたは、foreach代わりforループを使用することができ、確かに:

foreach (string line in lines) 
{ 
    sb.AppendLine(line); 
} 

あなたはまた、もはやのでint totalLines = lines.Count();ラインが必要になりますあなたが何かのためのカウントを必要としない(あなたがどこかであなたが表示されていない限り)。

+0

これはまだファイルを2回読み込みますが、最初のカウント( '.Count()'呼び出しがまだ存在していると仮定します)。 –

+0

@JonSkeet 'for'ループがない場合、初期カウントを計算する必要はありません。 – Servy

+0

@JonSkeet - 私はすでに読み込まれている 'lines'を使っています。あなたが何を言っているのか分かりません。 –

2

foreachについてはどうですか?この状況を正確に処理するように設計されています。

IEnumerable<String> lines = File.ReadLines("c:\myfile.txt", new UTF8Encoding()); 

StringBuilder sb = new StringBuilder(); 

string previousLine = null; 
int lineCounter = 0; 
int totalLines = lines.Count(); 

foreach (string line in lines) { 

    // show progress 
    float done = ++lineCounter/totalLines; 
    Debug.WriteLine($"{done*100:0.00}% complete"); 

    //get the line and do something 
    sb.AppendLine(line); 

    //do something else, like look at the previous line to compare 
    if (line == previousLine) { 
     Debug.WriteLine($"Line {lineCounter} is the same as the previous line."); 
    } 

    previousLine = line; 
} 
+0

私が考えている唯一の問題は、前の行を複数回参照する必要がある場合、混乱する可能性があるということです。あなたが中断した場所から行を解析し続ける必要があるとしたら、元に戻ってその行が新しい行になり、そこから続けると、foreachループは新しい繰り返しと同期しなくなります現在の行の前にある行を参照します。私は何を言っているのか見ていますか? – erotavlas

+0

私のコードでは、 'line'は常に最新です。 'previousLine'は常にその前のものです。ファイル内でポインタを移動していません。あなたはあなたが読んだ前の行を握っているだけです。同期が外れることはありません。 – Dan

関連する問題