Написание заголовка с использованием 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.

2 ответа

Вы можете быть озадачены тем, как работает 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 так что я положил его в блок использования.
  • Корректировка заработной платы слегка упрощена

Результат:

FirstName, LastName, оплате труда
Зигги,Walters,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);
    }

}

Результаты с использованием вывода из первого цикла в качестве входных данных:

FirstName, LastName, оплате труда
Зигги,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 со свойствами в вашем классе.

Я считаю, что это исключение из CsvReader, а не CsvWriter. CsvConfiguration по умолчанию ожидает заголовок и использует AutoMap для создания сопоставления PropertyName_to_Index.

Из документации вам может понадобиться определить карту, см. Карту

Другие вопросы по тегам