Csvhelper: カウントを取得

作成日 2018年03月12日  ·  5コメント  ·  ソース: JoshClose/CsvHelper

#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が重要です。

しかし、どうすればこれを回避できますか?

最も参考になるコメント

プログレスバーを更新するだけの場合は、最初にファイル全体を読み取らずに、大きなファイルで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;
}

全てのコメント5件

いくつかの方法があります。

  1. ToList実行して、すべてをメモリにプルします。 次に、 Countなど、データに対していくつかの操作を実行できます。
  2. ファイル全体をパーサーします。 パーサーだけを使用して、ファイル全体を調べ、レコードをカウントできます。 これは、クラスオブジェクトを作成したり、型変換を行ったりしないため、かなり高速になるはずです。
  3. ファイルの行末を数えるだけです。 その後、 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;
}

望ましい結果を得るために

このページは役に立ちましたか?
0 / 5 - 0 評価