#92でも同様の問題があります。 しかし、5年以上前の問題にぶつかるべきかどうかわからないので、新しい問題を作成しています。
列挙されたレコードでCount()
を呼び出すと、カーソルが最後に移動し、レコードでさらに操作/ foreach
ループが何も返さないことを認識しています。
私のコードの概要はこんな感じです
`` `` C#
var myCSV = new CsvReader(File.OpenText(txtBox_CSVFile.Text));
myCSV.Configuration.RegisterClassMap
var record = new MyRecordClass();
var allRecords = myCSV.EnumerateRecords(record);
int recordsLength = allRecords.Count<MyRecordClass>();
foreach (var r in allRecords)
{
/* some read/write operation here
*/
scannedCSVEntry++;
progress.value = scannedCSVEntry/recordsLength;
}
「」
エントリの処理中にプログレスバーを更新する必要があるため、ここではrecordsLength
が重要です。
しかし、どうすればこれを回避できますか?
いくつかの方法があります。
ToList
実行して、すべてをメモリにプルします。 次に、 Count
など、データに対していくつかの操作を実行できます。Context.RawRow
プロパティを使用して進行状況を確認できます。ありがとう、
私はついに方法2を選びました。
C#
StreamReader sr = File.OpenText(txtBox_CSVFile.Text);
int recordsLength = 0;
while(sr.ReadLine() != null)
{
++recordsLength;
}
recordsLength--; // discount 1 line because there are column headers in first row.
Console.WriteLine("recordsLength : " + recordsLength);
sr.Close();
EnumerateRecords()
は、すべてのエントリをハイドレイトした後、ストリームを自動的に閉じますか? 関数を呼び出した後、 Close()
を呼び出す必要があるかどうか疑問に思っています。
私の提案は、 using
ブロックでラップすることです。
using(StreamReader sr = File.OpenText(txtBox_CSVFile.Text))
{
int recordsLength = 0;
while(sr.ReadLine() != null)
{
++recordsLength;
}
recordsLength--; // discount 1 line because there are column headers in first row.
Console.WriteLine("recordsLength : " + recordsLength);
}
プログレスバーを更新するだけの場合は、最初にファイル全体を読み取らずに、大きなファイルでstream.Position
を使用するとうまくいきました。
using(StreamReader sr = File.OpenText(txtBox_CSVFile.Text))
{
var csvReader = new new CsvHelper.CsvReader(sr);
while (csvReader.Read())
{
double progress = (double)sr.BaseStream.Position / sr.BaseStream.Length;
}
}
GetRecordsでも機能するはずですが、テストしていません。
foreach(var record in csvReader.GetRecords<MyRecordClass>())
{
double progress = (double)sr.BaseStream.Position / sr.BaseStream.Length;
}
私はあなたの解決策をチェックしました
foreach(var record in csvReader.GetRecords<MyRecordClass>())
{
double progress = (double)sr.BaseStream.Position / sr.BaseStream.Length;
}
それは私にはうまくいきませんでした。
しかし、あなたはこれを行うことができます
foreach(var record in csvReader.GetRecords<MyRecordClass>())
{
double progress = (double)csvReader.Context.CharPosition / csvReader.Context.CharsRead;
}
望ましい結果を得るために
最も参考になるコメント
プログレスバーを更新するだけの場合は、最初にファイル全体を読み取らずに、大きなファイルで
stream.Position
を使用するとうまくいきました。GetRecordsでも機能するはずですが、テストしていません。