Работа с CSV в C# (.NET): обзор инструментов и примеры
CSV (Comma-Separated Values) — один из самых распространённых форматов для обмена табличными данными. В экосистеме C# (.NET) существует несколько надёжных способов работы с этим форматом: от встроенных средств до мощных сторонних библиотек. В этой статье мы рассмотрим основные подходы и лучшие практики.
Почему не стоит писать парсер CSV вручную?
Формат CSV на первый взгляд кажется простым, но на практике содержит много нюансов: экранирование кавычек, запятые внутри полей, разные разделители, символы новой строки в значениях. Использование готовых библиотек избавляет от головной боли и обработки краевых случаев.
Библиотека CsvHelper — золотой стандарт
CsvHelper — самая популярная библиотека для работы с CSV в .NET. Она поддерживает маппинг на POCO-классы, потоковое чтение, конфигурацию разделителей и кодировок.
Установка через NuGet:
Install-Package CsvHelper
Пример чтения CSV в список объектов
using CsvHelper;
using System.Globalization;
public class User
{
public int Id { get; set; }
public string Name { get; set; }
public string Email { get; set; }
}
var users = new List<User>();
using (var reader = new StreamReader("users.csv"))
using (var csv = new CsvReader(reader, CultureInfo.InvariantCulture))
{
users = csv.GetRecords<User>().ToList();
}
Пример записи CSV из коллекции
using (var writer = new StreamWriter("output.csv"))
using (var csv = new CsvWriter(writer, CultureInfo.InvariantCulture))
{
csv.WriteRecords(users);
}
Встроенный парсер: TextFieldParser (Microsoft.VisualBasic)
Если вы не хотите подключать внешние зависимости, в .NET есть встроенный TextFieldParser из пространства имён Microsoft.VisualBasic.FileIO. Он доступен в .NET Framework и .NET Core/.NET 5+ (требуется установка пакета Microsoft.VisualBasic).
Пример использования TextFieldParser
using Microsoft.VisualBasic.FileIO;
using (var parser = new TextFieldParser("data.csv"))
{
parser.TextFieldType = FieldType.Delimited;
parser.SetDelimiters(",");
parser.HasFieldsEnclosedInQuotes = true;
while (!parser.EndOfData)
{
string[] fields = parser.ReadFields();
Console.WriteLine(string.Join(" | ", fields));
}
}
Плюсы: не требует сторонних библиотек. Минусы: менее гибкий, чем CsvHelper, нет автоматического маппинга на классы.
Работа с большими файлами: потоковая обработка
При работе с CSV-файлами размером более 100 МБ важно избегать загрузки всего файла в память. Обе библиотеки поддерживают потоковую обработку:
- CsvHelper — используйте
GetRecords<T>()в циклеforeachбез вызова.ToList(). - TextFieldParser — читает строку за строкой, что также эффективно.
Пример потокового чтения с CsvHelper
using (var reader = new StreamReader("large.csv"))
using (var csv = new CsvReader(reader, CultureInfo.InvariantCulture))
{
foreach (var record in csv.GetRecords<User>())
{
ProcessUser(record); // обрабатываем по одному
}
}
Обработка ошибок и валидация данных
При импорте CSV данные могут быть некорректными. CsvHelper позволяет настраивать обработку ошибок через события:
csv.Configuration.BadDataFound = context =>
{
Console.WriteLine($"Ошибка в строке {context.RawRow}: {context.RawRecord}");
};
Также можно использовать атрибуты для валидации полей:
public class Product
{
[Name("ProductId")]
public int Id { get; set; }
[Required]
public string Name { get; set; }
[Default(0)]
public decimal Price { get; set; }
}
Работа с разными разделителями и кодировками
В реальных проектах часто встречаются TSV (табуляция), CSV с точкой с запятой (европейский формат). Настройка в CsvHelper:
var config = new CsvConfiguration(CultureInfo.InvariantCulture)
{
Delimiter = ";",
Encoding = Encoding.UTF8
};
Производительность: CsvHelper vs TextFieldParser
Бенчмарки показывают, что CsvHelper немного быстрее при работе с большими объёмами данных (особенно при маппинге на классы). TextFieldParser проигрывает из-за дополнительных проверок. Однако для большинства