web-dev-qa-db-ja.com

CsvHelperを使用してヘッダーを作成しますか? C#

私はCsvHelperを使用しています。 _.csv_ファイルに書き込むには、クラスに基づくヘッダーが必要です。

ヘッダーを手動で記述して機能しますが、読み取ったときに自動的に行う必要があります。

私が見つけることができるすべてのドキュメントは、この式writer.WriteHeader<CSVDataFormat>();を使用するように述べていますが、さらに作業が必要なため、機能していません。

ヘッダーの基になるクラスは次のとおりです。

_public class CSVDataFormat
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public float Wage { get; set; }
}
_

読み取りと書き込みのコードは次のとおりです。

_private void ReadCSV(string ogCsvFile)
{
        using (var streamReaederfileDir = new StreamReader(@ogCsvFile))
        {
            using (var streamWriterFileDir = new StreamWriter(Path.Combine(Path.GetDirectoryName(ogCsvFile), "New" + Path.GetFileName(ogCsvFile))))
            {
                var reader = new CsvReader(streamReaederfileDir);
                var writer = new CsvWriter(streamWriterFileDir);

                writer.WriteHeader<CSVDataFormat>();

                IEnumerable records = reader.GetRecords<CSVDataFormat>().ToList();

                foreach (CSVDataFormat record in records)
                {
                    record.Wage = record.Wage + (record.Wage / 10);
                    writer.WriteField(record.FirstName);
                    writer.WriteField(record.LastName);
                    writer.WriteField(record.Wage);
                    writer.NextRecord();
                }
            }
        }
}
_

更新

これは、コードを実行したときに発生するエラーです。

タイプ 'CsvHelper.CsvMissingFieldException'の未処理の例外がCsvHelper.dllで発生しました

追加情報:フィールド 'FirstName'はCSVファイルに存在しません。

6
Smithy

CSVHelperがどのように機能するか混乱するかもしれません。このコードは、読み取り/書き込みループの書き込みの側面を処理します。

List<Employee> empList = new List<Employee>();

empList.Add(new Employee { FirstName = "Ziggy", LastName = "Walters", Wage = 132.50F });
empList.Add(new Employee { FirstName = "Zoey", LastName = "Strand", Wage = 76.50F });

using (StreamWriter sw = new StreamWriter(@"C:\Temp\emp.csv"))
using (CsvWriter cw = new CsvWriter(sw))
{
    cw.WriteHeader<Employee>();

    foreach (Employee emp in empList)
    {
        emp.Wage *= 1.1F;
        cw.WriteRecord<Employee>(emp);
    }
}
  • CSVWriterIDisposableを実装しているので、usingブロックにも入れます。
  • 賃金調整はわずかに合理化されています

結果:

FirstName、LastName、Wage
Ziggy、Walters、145.75
Zoey、Strand、84.15

Writeヘッダーは、最初の行(列/アイテムの名前)を書き込むだけです。リストされている賃金は、私がそれぞれを作成するために使用したものとは異なることに注意してください。

あなたがしていることについては、empListを繰り返す代わりに、型付きオブジェクトを読み込みます。編集にリストされたエラーの場合、それは入力ファイルでその名前の列が見つからなかったことを意味します(おそらくTypesオーバーロードを使用しなかったため)。クラスプロパティ名は列名と正確に一致する必要があります(CSVHelperを構成することもできます)。


完全な入出力ループは、ほんの少しだけ複雑です。

using (StreamReader sr = new StreamReader(@"C:\Temp\empIN.csv"))
using (StreamWriter sw = new StreamWriter(@"C:\Temp\empOUT.csv"))
using (CsvWriter cw = new CsvWriter(sw))
using (CsvReader cr = new CsvReader(sr))
{
    cw.WriteHeader<Employee>();
    var records = cr.GetRecords<Employee>();

    foreach (Employee emp in records)
    {
        emp.Wage *= 1.1F;
        cw.WriteRecord<Employee>(emp);
    }

}

最初のループからの出力を入力として使用した結果:

FirstName、LastName、Wage
Ziggy、Walters、160.325
Zoey、Strand、92.565


受信CSVにヘッダーレコードがない場合、データをクラスにマップする方法がわかりません。マップを追加する必要があります:

public class EmployeeMap :  CsvHelper.Configuration.CsvClassMap<Employee>
{
    public EmployeeMap()
    {
        Map(m => m.FirstName).Index(0);
        Map(m => m.LastName).Index(1);
        Map(m => m.Wage).Index(2);
    }
}

鉱山はEmployeeクラス内にネストされています。次に、CSVHelperにそのマップを提供します。

... before your try to read from the incoming CSV:
cr.Configuration.RegisterClassMap<Employee.EmployeeMap>();

cw.WriteHeader<Employee>();
...

これで、csv列をクラスのプロパティにマップする方法がわかりました。

この例外はCsvWriterからのものであり、CsvWriterからのものではないと思います。デフォルトのCsvConfigurationはヘッダーを想定し、AutoMapを使用してPropertyName_to_Indexマッピングを生成します。

ドキュメントから、マップを定義する必要があるかもしれません マッピングを参照

0
Steve