C# прочитать csv с 2 строками в заголовке
Может кто подскажет как это сделать.
Есть такой csv
;;temperature ID1;water ID1
;;C;moh
2022.05.22;07:00;8,5;499,24
2022.05.22;08:00;10,3;499,24
Как видно из приведенного куска файла, имеется две строки заголовка в начале, да еще и с пустыми значениями.
На выходе я хочу иметь вот такой набор значений
public class Records
{
public DateOnly Dates { get; set; }
public string Times { get; set; }
public float Moh { get; set; }
public float Temperature { get; set; }
}
Попробовал решить через ручную обработку и она естественно работает. Меня беспокоит только, что приходится разделять по \r\n, поскольку нет гарантии существования этого разделителя в файлах. Вот это
List<Records> records = new List<Records>();
using (var reader = new StreamReader("csvs\\test.csv"))
{
while (!reader.EndOfStream)
{
var line = reader.ReadLine();
var values = line.Split("\r\n");
foreach (var item in values)
{
var values_sep = item.Split(";");
try
{
var record = new Records{
Dates = DateOnly.Parse(values_sep[0]),
Times = values_sep[1],
Moh = float.Parse(values_sep[2]),
Temperature = float.Parse(values_sep[3])
};
records.Add(record);
}
catch (System.Exception)
{
System.Console.WriteLine("error");
}
}
}
}
Далее я попробовал CsvHelper, но настройка конфигурации сбивает с толку и получилось отделить полезную нагрузку от заголовков только через switch/case. Поставил заглушки в виде System.Console.WriteLine, чтоб не загромождать код.
var config = new CsvConfiguration(CultureInfo.InvariantCulture)
{
HasHeaderRecord = false,
Delimiter=";"
};
using (var reader = new StreamReader("csvs\\test.csv"))
using (var csv = new CsvReader(reader, config))
{
while (csv.Read())
{
switch (csv.GetField(0))
{
case "":
System.Console.WriteLine("Headers Here");
break;
default:
System.Console.WriteLine("Record here");
break;
}
}
}
Собственно вопрос, есть ли возможность читать такого плана csv файлы без костылей и хардкода? Или мои решения вполне приемлимы в области C#?
Ответы (2 шт):
Csv csv = new Csv(); //создаем инстанс читалки
csv.FileOpen("c:\\file1.csv"); //открываем файл
дальше парсим лист строк в обьект Records (кстате лучше рекорд а не рекордС )
по мере необходимости сравниваем заголовок в первой строке, т.е. в
csv.Rows[0]
с ячейками внутри и тогда парсим.
Ничего особо сложного
Я не понял, зачем вы разделяете строки по \r\n. Ведь метод ReadLine класса StreamReader уже выдаёт вам готовую строку без этих символов.
Если нужно пропустить две строки заголовка, то это проще всего сделать с помощью linq-метода Skip:
File.ReadLines("test.csv").Skip(2)
Если нет гарантии, что заголоки присутствуют в файле, то фильтруем с помощью Where:
File.ReadLines("test.csv").Where(x => x[0] != ';')
Итоговый код может выглядеть так:
var records = new List<Records>();
foreach (var line in File.ReadLines("test.csv").Where(x => x[0] != ';'))
{
var values = line.Split(";");
var record = new Records
{
Dates = DateOnly.Parse(values[0]),
Times = values[1],
Moh = float.Parse(values[2]),
Temperature = float.Parse(values[3])
};
records.Add(record);
}
Или весь на LINQ:
var records = File.ReadLines("test.csv")
.Skip(2) // или Where
.Select(line =>
{
var values = line.Split(";");
return new Records
{
Dates = DateOnly.Parse(values[0]),
Times = values[1],
Moh = float.Parse(values[2]),
Temperature = float.Parse(values[3])
};
})
.ToList();