Работа с CSV в C# (.NET): от простого парсинга до продвинутой библиотеки
CSV (Comma-Separated Values) — один из самых распространённых форматов для обмена табличными данными. В экосистеме .NET существует несколько подходов к работе с CSV: от встроенных средств до специализированных библиотек. В этой статье мы разберём все основные способы, покажем примеры кода и поможем выбрать оптимальный инструмент для вашего проекта.
1. Встроенные средства .NET (ручной парсинг)
Самый простой способ — использовать классы StreamReader и String.Split. Однако этот метод не учитывает экранирование кавычек и запятых внутри полей, поэтому подходит только для простых CSV-файлов без сложных данных.
using System;
using System.IO;
using System.Linq;
public class SimpleCsvReader
{
public static void ReadCsv(string filePath)
{
using (var reader = new StreamReader(filePath))
{
while (!reader.EndOfStream)
{
var line = reader.ReadLine();
var values = line.Split(',');
// Обработка строки
Console.WriteLine(string.Join(" | ", values));
}
}
}
}
Недостатки: не обрабатывает кавычки, не поддерживает многострочные поля, нет типизации.
2. Использование TextFieldParser (Microsoft.VisualBasic)
Класс TextFieldParser из пространства имён Microsoft.VisualBasic.FileIO умеет корректно обрабатывать CSV с кавычками и разделителями. Для использования добавьте ссылку на сборку Microsoft.VisualBasic.
using Microsoft.VisualBasic.FileIO;
using System;
public class TextFieldParserExample
{
public static void ParseCsv(string filePath)
{
using (var parser = new TextFieldParser(filePath))
{
parser.TextFieldType = FieldType.Delimited;
parser.SetDelimiters(",");
parser.HasFieldsEnclosedInQuotes = true;
while (!parser.EndOfData)
{
string[] fields = parser.ReadFields();
Console.WriteLine(string.Join(" | ", fields));
}
}
}
}
Этот метод уже лучше, но всё ещё требует ручного маппинга полей в объекты.
3. Библиотека CsvHelper — золотой стандарт
CsvHelper — самая популярная библиотека для работы с CSV в .NET. Она обеспечивает полную поддержку стандарта RFC 4180, автоматическое маппинг на классы, поддержку LINQ и высокую производительность.
Установка
dotnet add package CsvHelper
Пример чтения CSV в список объектов
using CsvHelper;
using CsvHelper.Configuration;
using System.Globalization;
using System.IO;
using System.Linq;
public class Person
{
public int Id { get; set; }
public string Name { get; set; }
public string Email { get; set; }
public DateTime BirthDate { get; set; }
}
public class CsvHelperReader
{
public static List<Person> ReadPeople(string filePath)
{
using (var reader = new StreamReader(filePath))
using (var csv = new CsvReader(reader, CultureInfo.InvariantCulture))
{
return csv.GetRecords<Person>().ToList();
}
}
}
Пример записи CSV из коллекции
public static void WritePeople(string filePath, List<Person> people)
{
using (var writer = new StreamWriter(filePath))
using (var csv = new CsvWriter(writer, CultureInfo.InvariantCulture))
{
csv.WriteRecords(people);
}
}
Расширенное конфигурирование
var config = new CsvConfiguration(CultureInfo.InvariantCulture)
{
HasHeaderRecord = true,
Delimiter = ";", // Использовать точку с запятой
MissingFieldFound = null, // Игнорировать отсутствующие поля
TrimOptions = TrimOptions.Trim
};
using (var csv = new CsvReader(reader, config))
{
// ...
}
4. Работа с большими файлами (стриминг)
CsvHelper поддерживает потоковую обработку, что позволяет читать файлы любого размера без загрузки всего содержимого в память:
using (var reader = new StreamReader("large.csv"))
using (var csv = new CsvReader(reader, CultureInfo.InvariantCulture))
{
// Читаем записи по одной
foreach (var record in csv.GetRecords<MyRecord>())
{
ProcessRecord(record); // Обработка каждой записи
}
}
5. Работа с динамическими объектами
Если структура CSV заранее неизвестна, можно использовать динамические типы:
using (var reader = new StreamReader("data.csv"))
using (var csv = new CsvReader(reader, CultureInfo.InvariantCulture))
{
// Читаем как динамические объекты
foreach (var record in csv.GetRecords<dynamic>())
{
Console.WriteLine(record.Name);
Console