使用CsvHelper编写标题? C#

时间:2016-06-29 00:25:59

标签: c# .net csv csvhelper

我正在使用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.dll中出现未处理的“CsvHelper.CsvMissingFieldException”类型异常

     

其他信息:CSV文件中不存在字段'FirstName'。

2 个答案:

答案 0 :(得分:10)

您可能会对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);
    }
}
  • CSVWriter实现IDisposable,因此我也将其放入使用块中。
  • 工资调整略有精简

结果:

  

名字,姓氏,工资
  齐格,沃尔特斯,145.75
  Zoey,Strand,84.15

写标题只写第一行 - 列/项的名称。请注意,列出的工资与我用来创建工资的工资不同。

对于你正在做的事情,我会读取一个打字对象,而不是迭代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);
    }

}

结果使用第一个循环的输出作为输入:

  

名字,姓氏,工资
  齐格,沃尔特斯,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);
    }
}

Mine嵌套在Employee类中。然后给CSVHelper映射:

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

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

现在它知道如何将csv列映射到类中的属性。

答案 1 :(得分:0)

我相信这个例外来自CsvReader而不是CsvWriter。默认CsvConfiguration需要标头并使用AutoMap生成PropertyName_to_Index映射。

您可能需要从文档中定义地图 see mapping