CSV — не «просто текст». Практика CSV в бизнес-приложениях на C# (кодировки, совместимость с Excel, защита от инъекций)

· Обновлено: · · CSharp, .NET, CSV, Excel, Кодировки символов, Интеграция файлов, Разработка под Windows, Техническая консультация

История изменений (3 обновлений, последнее 31 Aug 2026)

Журнал изменений этой статьи. Там, где версия до правки была заархивирована, она остаётся доступной для чтения по постоянной ссылке с DOI.

Текст статьи исправлен, чтобы соответствовать японскому оригиналу.
Переведены названия источников в списке литературы. Утверждения статьи не менялись.
Русский текст переписан как полноценный технический перевод, а не калька с японского. Утверждения статьи не менялись.
Первая публикация
Цитирование статьи(DOI (зарегистрированный архив): 10.5281/zenodo.21620011)

Приведённые ниже DOI относятся к ранее зарегистрированным архивным версиям, которые могут отличаться от текущего текста. Для ссылки на текущий текст используйте URL этой страницы.

Го Комура (2026). CSV — не «просто текст». Практика CSV в бизнес-приложениях на C# (кодировки, совместимость с Excel, защита от инъекций). KomuraSoft LLC. https://comcomponent.com/ru/blog/csv-file-handling-practical-guide/

DOI (зарегистрированный архив)
10.5281/zenodo.21620011
DOI (последняя зарегистрированная версия)
10.5281/zenodo.21620012

Обмен данными через CSV по-прежнему один из основных способов интеграции в бизнес-приложениях. И именно потому, что формат выглядит как «просто склеить текст запятыми», здесь снова и снова случаются одни и те же сбои: самописный парсер ломается на запятой внутри поля, при открытии в Excel текст искажается, у номера телефона пропадает начальный ноль.

В статье мы рассматриваем бизнес-приложения на C#, которые читают и пишут CSV, и разбираем спецификацию CSV (RFC 4180) и реальные диалекты, выбор кодировки, проблемы совместимости с Excel, защиту от CSV-инъекций и эксплуатационные ловушки — в том порядке, в котором на практике обычно возникают сомнения при принятии решений.

1. Сначала выводы (таблица решений)

Проектные решения по CSV нужно выводить от ответа на вопрос «кто (или что) будет открывать этот файл». Глава состоит из двух частей. Таблица решений (1.1) — справочник «для такой задачи — такой выбор». Принципы (1.2) — пять правил, которые работают независимо от назначения. В столбце «Подробнее» стоят ссылки на соответствующие главы, поэтому можно читать только нужные разделы.

1.1 Кодировку выбирают по назначению (таблица решений)

Назначение Предпочтительная кодировка На что обратить внимание при проектировании Подробнее
Человек открывает файл двойным щелчком в Excel UTF-8 (с BOM) Без BOM в части окружений Excel неверно определяет кодировку, и текст искажается. Потерю начальных нулей и преобразование в даты кодировка не предотвращает 4.1 / глава 5
Новая интеграция между системами UTF-8 (без BOM) В спецификации явно указать кодировку, правила кавычек, символ переноса строки и наличие заголовка. Наличие или отсутствие BOM тоже зафиксировать глава 2 / 4.1
Интеграция с унаследованной системой Следовать спецификации контрагента (часто Shift_JIS) В .NET (Core) для Shift_JIS нужно зарегистрировать CodePagesEncodingProvider. Заранее договориться, как обрабатывать платформенно-зависимые символы 4.2
Пакетный обмен большими объёмами Следовать спецификации Не загружать все записи в память, обрабатывать потоково по одной строке. Заложить исключающую блокировку и обработку недописанных файлов глава 7
Вывод данных, в которых есть пользовательский ввод По назначению Если не нейтрализовать значения, которые начинаются с = или +, в окружении того, кто откроет файл, может выполниться формула глава 6
Главная цель — просмотр и печать человеком в Excel — Имеет смысл рассмотреть вывод в xlsx вместо CSV (см. FAQ) глава 5

1.2 Принципы, которые действуют всегда

Сначала зафиксируем выводы, общие для любого назначения.

  • Разбор CSV через String.Split(',') ломается по спецификации, даже если сейчас «всё работает». Он не обрабатывает запятые, переносы строк и кавычки внутри полей. В стандартном .NET используйте TextFieldParser (глава 3).
  • Сбои кодировки возникают из-за того, как файл интерпретирует Excel. Для CSV, которые люди открывают в Excel, сегодня разумный выбор — UTF-8 с BOM. В .NET есть ещё одна ловушка: появится BOM или нет, зависит от того, как задан Encoding (глава 4).
  • В .NET (Core) Shift_JIS без дополнительного пакета недоступен. Encoding.GetEncoding("shift_jis") сработает только после регистрации CodePagesEncodingProvider из пакета System.Text.Encoding.CodePages1. Типичное место, где обработка CSV, перенесённая с .NET Framework, впервые выбрасывает исключение уже в продакшене (4.2).
  • Потерю начальных нулей и преобразование в дату средствами CSV не предотвратить. Важно, что двойные кавычки вокруг поля тоже не помогают (глава 5).
  • Приложениям, которые выводят пользовательский ввод в CSV, нужна защита от CSV-инъекций. Поля, которые начинаются с = или +, Excel интерпретирует как формулы (глава 6).

На схеме сплошная линия обозначает отношение, которое выполняется всегда, а пунктирная — условное отношение (условия указаны в пояснении к каждому отношению на странице сведений). Полный список отношений (всего 24, с доказательствами и степенью уверенности) и определения основных понятий собраны на странице сведений карты знаний (на японском). Данные: JSON-LD / Turtle

2. «Спецификация» CSV — RFC 4180 и реальные диалекты

У CSV есть фактический стандарт — RFC 41802. На практике достаточно четырёх правил.

  1. Записи разделяются переносом строки (CRLF), поля — запятой.
  2. Если поле содержит запятую, перенос строки или двойную кавычку, всё поле целиком заключают в двойные кавычки.
  3. Двойную кавычку внутри поля экранируют удвоением: "".
  4. Поля, которые не обязаны быть в кавычках, можно заключать в кавычки или оставлять как есть.

То есть следующая строка — это запись из трёх полей.

1001,"ООО «Образец» отдел продаж","Адрес: ""Москва, район ○○, 1-2-3"", и в этой заметке есть запятая"

При этом RFC 4180 — лишь «фактический» стандарт, и у реальных CSV множество диалектов: перенос строки только LF, нет обработки кавычек, разделитель — табуляция или точка с запятой, строка заголовка то есть, то нет. Поэтому в спецификации интеграции написать «соответствует RFC 4180» и явно зафиксировать кодировку, наличие BOM, символ переноса строки и наличие заголовка — самая выгодная по затратам мера против будущих сбоев.

3. Не пишите парсер на Split(‘,’) самостоятельно — практика чтения

С учётом правил из предыдущей главы причина поломки String.Split(',') очевидна. Запятая внутри поля даёт лишнее разбиение, а перенос строки внутри кавычек обрывает строку посередине. То, что сейчас «работает», объясняется лишь тем, что в текущих файлах нет данных с запятыми внутри полей. В зависимости от данных это сломается в любой момент.

Если нужно корректно читать CSV средствами стандартного .NET, подходит Microsoft.VisualBasic.FileIO.TextFieldParser. Пространство имён относится к Visual Basic, но из C# класс используют обычным образом3.

using Microsoft.VisualBasic.FileIO; // Microsoft.VisualBasic.Core (входит в SDK для Windows-десктопа)

using var parser = new TextFieldParser(path, System.Text.Encoding.UTF8)
{
    TextFieldType = FieldType.Delimited,
    HasFieldsEnclosedInQuotes = true, // корректно обрабатывать поля, заключённые в кавычки
    TrimWhiteSpace = false, // по умолчанию true (пробелы по краям молча удаляются). Отключите, если пробелы значат что-то в данных
};
parser.SetDelimiters(",");

while (!parser.EndOfData)
{
    try
    {
        string[]? fields = parser.ReadFields();
        if (fields is null) break;
        // обработать fields[0], fields[1], ...
    }
    catch (MalformedLineException ex)
    {
        // повреждённая строка: содержимое и номер строки можно записать через ErrorLine / ErrorLineNumber
        logger.LogWarning("Некорректный формат строки {Line} в CSV: {Content}",
            ex.LineNumber, parser.ErrorLine);
    }
}

Практический плюс TextFieldParser в том, что помимо обработки кавычек (HasFieldsEnclosedInQuotes) он обнаруживает повреждённые строки как MalformedLineException с номером строки3. При импорте CSV в бизнес-приложении спецификация как раз и расходится на развилке «отклонить весь файл, если сломана одна строка, или пропустить только её и сообщить». Эту обработку исключений можно сразу перенести в спецификацию.

Если нужны сопоставление столбцов с объектами, преобразование типов и производительность на миллионах строк, рассмотрите проверенную CSV-библиотеку. В .NET чаще всего используют CsvHelper (пакет NuGet тоже называется CsvHelper): он явно заявляет соответствие RFC 4180, лицензирован по двойной лицензии MS-PL и Apache 2.0 и допускает коммерческое использование4. Есть сопоставление с классами, привязка имён столбцов через ClassMap и отложенное чтение через IEnumerable<T>. Когда этап «приняли string[] из TextFieldParser и сами преобразуем типы» уже пройден, это первый кандидат на переход.

Впрочем, важнее не то, какую библиотеку выбрать, а что проверить при выборе. Смотрите четыре пункта: обработка кавычек по RFC 4180, задание кодировки, поведение на повреждённых строках и возможность потокового чтения. Если эти четыре условия выполнены, на практике сильно не промахнётесь. Если внутренние правила ограничивают внешние пакеты, сначала оцените, хватает ли TextFieldParser.

На стороне записи спецификация проще, поэтому свою реализацию делать можно, но экранирование обязательно соберите в одну функцию.

// Вся логика экранирования при записи собрана в этой единственной функции
static string ToCsvField(string? value)
{
    value ??= string.Empty;
    bool needsQuoting = value.Contains(',') || value.Contains('"')
        || value.Contains('\r') || value.Contains('\n');
    return needsQuoting ? $"\"{value.Replace("\"", "\"\"")}\"" : value;
}

Что делает функция, сразу видно, если сопоставить вход и выход.

Вход (содержимое строки C#) Возвращаемое значение ToCsvField Почему
Москва Москва Особых символов нет, оставляем как есть
ООО «Образец», отдел продаж "ООО «Образец», отдел продаж" Есть запятая, поэтому поле целиком в кавычках
Адрес: "Москва" "Адрес: ""Москва""" Кавычки заменяем на "", затем заключаем всё поле
Строка 1(перевод строки)Строка 2 "Строка 1(перевод строки)Строка 2" Есть перенос строки, поэтому в кавычках. Тогда поле читается как одно
null (пустая строка) ??= сводит значение к пустой строке

Ключевой момент — порядок в третьей строке: «сначала заменить, потом заключить в кавычки». Если сделать наоборот, в "" превратятся и те кавычки, которые вы сами поставили вокруг поля, и запись сломается. Достаточно одного места, где столбец с суммой по-прежнему собирают вручную через string.Join, — именно оно потом станет источником сбоя.

4. Кодировки — поведение Excel и ловушки .NET

4.1 Если файл открывают в Excel — UTF-8 с BOM

Большинство случаев искажения текста в CSV происходит потому, что Excel неверно определяет кодировку файла. Если CSV в UTF-8 без BOM (BOM — несколько байт-меток в начале файла) открыть двойным щелчком, в части окружений его воспримут как ANSI (в японском окружении — как Shift_JIS), и японский текст пропадёт целиком. UTF-8 с BOM распознаётся как UTF-8, поэтому для CSV, которые люди открывают двойным щелчком в Excel, сегодня разумный выбор — UTF-8 с BOM.

Оговорка «в части окружений» нужна потому, что глубина автоопределения UTF-8 без BOM зависит от версии и сборки Excel и от региональных настроек ОС, и нельзя утверждать, какая именно версия всегда определяет кодировку верно. На что можно опереться — текущая статья поддержки Microsoft, где сказано следующее5.

Состояние файла Рекомендация Microsoft
UTF-8 с BOM Открывается обычным способом
UTF-8 без BOM Открывать через Power Query (вкладка [Данные] > [Получить данные] > [Из файла] > [Из текста/CSV]) либо указать кодировку в мастере импорта

То есть успешное открытие UTF-8 без BOM двойным щелчком официально не обещают. В бизнес-приложении, где версию Excel и региональные настройки у получателя вы сами не проверите, меньше обращений в поддержку даёт правило «поставить BOM и оставить файл открываемым двойным щелчком». Наоборот, если файл забирает система, BOM — лишние три байта и типичная причина ошибки разбора, поэтому BOM не ставят.

Сам BOM — это три байта EF BB BF в начале файла. В двоичном редакторе или через Format-Hex в PowerShell по началу файла сразу видно, какой вариант записан.

UTF-8 с BOM:   EF BB BF 44 61 74 65 2C ...   ← первые 3 байта EF BB BF, затем идёт "Date,"
UTF-8 без BOM: 44 61 74 65 2C ...            ← сразу начинается с "Date,"

И «в файле, который должен быть с BOM, нет EF BB BF в начале», и «на стороне загрузки не совпадает только имя первого столбца (невидимые три байта приклеились к началу имени)» — оба случая по этим трём байтам диагностируются за пять секунд.

К этому добавляется ловушка на стороне .NET: появится BOM или нет, зависит от того, как передают Encoding.

// UTF-8 без BOM: значение по умолчанию, если кодировку не указали
File.WriteAllText(path, csv);

// UTF-8 с BOM: статическое свойство Encoding.UTF8 настроено на вывод BOM
File.WriteAllText(path, csv, Encoding.UTF8);

// Если намерение нужно выразить явно, однозначнее задать его конструктором
File.WriteAllText(path, csv, new UTF8Encoding(encoderShouldEmitUTF8Identifier: true));

То, что итоговый файл отличается в зависимости от того, передали Encoding.UTF8 или кодировку опустили, — поведение, о котором нельзя догадаться, не зная его заранее6. Если в спецификации зафиксировали «без BOM для интеграции между системами» и «с BOM для Excel», в коде тоже лучше явно выражать намерение через new UTF8Encoding(...).

4.2 Чтобы использовать Shift_JIS в .NET (Core), нужна регистрация

При интеграции с унаследованными системами CSV в Shift_JIS (кодовая страница 932) до сих пор в ходу. Важно вот что: .NET (Core) / .NET 5 и новее по умолчанию поддерживают лишь небольшой набор кодировок — в основном семейство Unicode и ASCII. Вызов Encoding.GetEncoding("shift_jis") будет выбрасывать исключение, пока не добавлен пакет System.Text.Encoding.CodePages и не зарегистрирован CodePagesEncodingProvider1.

using System.Text;

// Регистрируется один раз при запуске приложения (например, в Program.cs)
Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);

// После этого можно получить Shift_JIS (кодовая страница 932)
Encoding sjis = Encoding.GetEncoding("shift_jis");

Классический сбой: приложение перенесло обработку CSV с эпохи .NET Framework на .NET, в продакшене впервые получает файл в Shift_JIS и падает с исключением. Что проверять при миграции, собрано в статье «Чек-лист перед миграцией с .NET Framework на .NET».

Кроме того, раз используется Shift_JIS, не обойти платформенно-зависимые символы (①, ㈱ и подобные), проблему волнообразного тире (wave dash) и потерю символов, которые есть только в Unicode. Основы этих кодировок подробно разобраны в статьях «Кодировки символов Windows и механизм искажения текста» и «Практика работы с кодировками и переводами строк в Windows».

5. Данные, которые ломаются при открытии в Excel — потеря начальных нулей, преобразование в дату, экспоненциальная запись

Даже при правильной кодировке при просмотре в Excel остаётся ещё одна группа проблем: при открытии CSV Excel «интерпретирует» значения.

Исходные данные Отображение в Excel Что произошло
09012345678 (номер телефона) 9012345678 Интерпретируется как число, начальный ноль пропадает. 11 цифр становятся 10, как телефон номер уже не использовать
007 (код товара) 7 То же самое
1-1 (дополнительный номер) 1 января Интерпретируется как дата
1234567890123456 (16-значный учётный номер) 1.23457E+15 Превращается в экспоненциальную запись, младшие разряды теряются

И важно, что эти проблемы не решаются даже заключением поля в двойные кавычки. Кавычки лишь обозначают синтаксическую границу поля в CSV, а Excel заново интерпретирует содержимое.

На практике есть три варианта.

  1. Просить открывать файл правильным способом в Excel. Не двойным щелчком, а через «Получение данных (из текста/CSV)» с типом столбца «Текст» — тогда данные не повредятся. Это стоит записать в регламент эксплуатации.
  2. Если главная цель — просмотр, выводить xlsx. Формат ячеек задаёт сторона вывода, и вся эта группа проблем исчезает. Как делать вывод файлов Excel, см. «Как реализовать вывод отчётов Excel». Автоматизация Excel через COM на сервере или в службе не рекомендуется: как написано в «Проблеме остающихся процессов EXCEL.EXE», это типичный источник зависших процессов, поэтому выбирайте вывод через библиотеки.
  3. Вывод в виде ="007" — крайняя мера. В Excel значение отображается как текст, но для CSV это уже «нестандартный файл с формулой внутри», и загрузка в системах помимо Excel ломается. Не используйте этот приём для файла, который одновременно забирает другая система.

6. CSV-инъекция — не превращайте пользовательский ввод в формулы

В приложениях, которые выводят введённые пользователем значения (имя, примечание, адрес) в CSV и дают открыть его в Excel, есть вектор атаки CSV-инъекция. Поля, которые начинаются с =, +, -, @ и подобных символов, Excel интерпретирует как формулы, поэтому вредоносный ввод (например, формула вида =cmd|'/C calc'!A0, рассчитанная на запуск внешнего процесса) может выполниться в окружении другого пользователя, который откроет этот CSV7.

Базовая мера — при выводе нейтрализовать опасные начальные символы.

// Перед полем, которое могут принять за формулу, ставим одинарную кавычку.
// В японском окружении полноширинные =+-@ тоже могут считаться началом формулы, поэтому включаем их в проверку
static string SanitizeForExcel(string value)
{
    if (value.Length > 0 && value[0]
        is '=' or '+' or '-' or '@' or '\t' or '\r' or '\n'
        or '=' or '+' or '-' or '@')
    {
        return "'" + value;
    }
    return value;
}

Одинарная кавычка в начале для Excel — признак «обрабатывать как текст». Список опасных начальных символов зависит от реализации и версии табличного процессора, поэтому такую нейтрализацию устойчивее проектировать в другую сторону: «пропускать без изменений только если первый символ входит в список разрешённых (буквы, цифры и т. п.)» — так меньше риск упустить непредвиденный случай. Но если этот CSV забирает другая система, одинарная кавычка останется в данных; возможно и решение разделить файлы на «для открытия в Excel» и «для загрузки в систему». Сочетать ли это с проверкой ввода (например, вообще не разрешать начальный =), а также общее проектирование безопасности приложения см. в «Минимальном чек-листе безопасности Windows-приложений».

7. Эксплуатационные ловушки — где всё ломается помимо формата

Наконец, места, где на практике случаются сбои вне синтаксиса CSV.

  • Не ставьте формат чисел и дат в зависимость от культуры ОС. value.ToString() зависит от региональных настроек операционной системы. В регионах, где десятичный разделитель — запятая, значение выйдет как 1,5 и столкнётся с разделителем CSV. Для преобразований в файловом обмене явно указывайте CultureInfo.InvariantCulture, а даты выводите в фиксированном формате, например yyyy-MM-dd. Проектирование дат подробно разобрано в «Проектировании даты, времени и часовых поясов в бизнес-приложениях».
  • Большие данные обрабатывайте потоково — но допустимость «по одной строке» зависит от спецификации. File.ReadAllLines кладёт все строки в память как массив и для больших файлов не подходит8. Заменять его на File.ReadLines (отложенное перечисление) или на построчное чтение через StreamReader можно только для файлов, в спецификации которых явно сказано, что переносы строк внутри полей не допускаются. В CSV по RFC 4180 перенос строки внутри кавычек разрешён, и разбиение по строкам разрежет одну запись посередине. Тогда используйте TextFieldParser, который читает напрямую по пути к файлу (файл целиком в память не загружает), либо потоковое чтение CSV-библиотеки.
  • Не отдавайте на чтение «недописанный файл» и сами его не читайте. Базовая схема файлового обмена — сторона вывода пишет во временный файл и затем переименовывает его, сторона загрузки проверяет блокировку перед чтением — разобрана в «Основах исключающей блокировки при файловой интеграции», а нюансы загрузки через наблюдение за папкой — в «Практическом руководстве по FileSystemWatcher».
  • Заложите изменение числа столбцов. Зафиксируйте в спецификации, будет ли сопоставление «по именам столбцов в строке заголовка» или «фиксированный порядок столбцов, проверка их числа и отказ при несовпадении». Неявные обращения по магическим номерам вроде fields[7] тихо ломаются, едва контрагент добавит столбец.
  • Заранее решите, как обрабатывать завершающий перевод строки и пустые строки. Есть ли перевод строки после последней строки, пропускать пустые строки или отклонять файл — места, где парсеры расходятся. TextFieldParser пустые строки пропускает3.

Итог

CSV выглядит как формат, где «данные просто разделены запятыми», а на деле это формат интеграции с множеством диалектов. На практике достаточно четырёх пунктов: для чтения берите компонент, который умеет кавычки (не пишите парсер на Split самостоятельно); кодировку выбирайте от того, кто будет открывать файл (особенно Excel), и в спецификации фиксируйте в том числе наличие BOM; учитывайте, что интерпретацию значений Excel (потерю нулей, преобразование в дату) средствами CSV не предотвратить; если выводите пользовательский ввод — добавьте защиту от инъекций. Уже это позволяет отсечь большинство сбоев CSV-интеграции ещё на этапе проектирования.

Разбор искажения кодировки и повреждения данных в существующей интеграции через CSV, уточнение спецификации обмена с унаследованными системами, новая реализация импорта и экспорта CSV часто требуют решений по живым файлам и спецификации контрагента. Если сомневаетесь — обращайтесь.

Связанные статьи

Похожие направления консультаций

ООО «Комура Софт» консультирует по разработке бизнес-приложений, включая интеграцию через CSV и файлы, по разбору причин искажения кодировки и повреждения данных в существующей интеграции и по уточнению спецификации обмена с унаследованными системами.

Источники

  1. Microsoft Learn, CodePagesEncodingProvider Class. О том, что .NET Core по умолчанию поддерживает только ASCII, ISO-8859-1 и кодировки семейства Unicode, а для кодовых страниц вроде Shift_JIS (кодовая страница 932) нужно зарегистрировать CodePagesEncodingProvider из System.Text.Encoding.CodePages через Encoding.RegisterProvider. ↩ ↩2

  2. IETF, RFC 4180 - Common Format and MIME Type for Comma-Separated Values (CSV) Files. Фактический стандарт формата CSV. Об обработке кавычек для запятых, переносов строк и двойных кавычек внутри полей и об экранировании через "". ↩

  3. Microsoft Learn, TextFieldParser Class. О разборе текста с разделителями и фиксированной длиной полей, обработке кавычек через HasFieldsEnclosedInQuotes, исключении MalformedLineException со свойствами ErrorLine/ErrorLineNumber для строк, которые не удаётся разобрать, и о том, что ReadFields пропускает пустые строки. ↩ ↩2 ↩3

  4. Официальная документация CsvHelper, CsvHelper. О том, что это библиотека чтения и записи CSV для .NET, заявляет соответствие RFC 4180 и доступна для коммерческого использования по двойной лицензии Microsoft Public License (MS-PL) и Apache License 2.0. ↩

  5. Microsoft Support, Opening CSV UTF-8 files correctly in Excel. О том, что CSV в UTF-8, сохранённый с BOM, открывается обычным способом, а без BOM его нужно открывать через [Данные] > [Получить данные] > [Из файла] > [Из текста/CSV] (Power Query) либо через мастер импорта. ↩

  6. Microsoft Learn, UTF8Encoding Class. Об управлении выводом BOM (U+FEFF) через параметр encoderShouldEmitUTF8Identifier и о том, что экземпляр, который возвращает свойство Encoding.UTF8, настроен на вывод BOM. ↩

  7. OWASP, CSV Injection. Об атаке (Formula Injection), при которой поля, начинающиеся с =, +, -, @, табуляции или символа возврата каретки, табличный процессор интерпретирует как формулы, и о мерах защиты. ↩

  8. Microsoft Learn, File.ReadLines Method. О том, что в отличие от ReadAllLines, который возвращает массив всех строк, ReadLines возвращает перечисляемую коллекцию, и перечисление большого файла можно начать, не дожидаясь загрузки целиком. ↩

Недавние статьи с теми же тегами помогут подробнее изучить близкие темы.

Эти страницы показывают тему статьи в более широком контексте услуг и решений.

Статья напрямую связана со следующими услугами.

Частые вопросы

Вопросы, которые часто возникают при консультациях по теме статьи.

Какую кодировку выбирать для CSV?
Главное правило: если получатель уже известен, подстраивайтесь под его спецификацию. Если формат можно задать с нуля, разумная отправная точка такая: файлы, которые люди открывают в Excel, — UTF-8 с BOM; интеграция между системами — UTF-8 без BOM; и то и другое явно зафиксировать в спецификации. Если при обмене с унаследованной системой требуют Shift_JIS, заранее договоритесь, как обрабатывать платформенно-зависимые символы и внешние иероглифы (外字). Иначе потом начнётся спор, кто виноват в искажении текста.
Нужна ли библиотека для CSV или достаточно своей реализации?
Для чтения своей реализации на String.Split недостаточно: по спецификации она не умеет корректно обрабатывать запятые, переносы строк и кавычки внутри полей, поэтому нужен готовый компонент. В стандартном .NET класс TextFieldParser поддерживает обработку кавычек на уровне RFC 4180. Если нужны сопоставление столбцов с объектами, преобразование типов и производительность на больших объёмах, имеет смысл взять проверенную CSV-библиотеку. Запись проще, поэтому свою реализацию делать можно, но экранирование кавычек соберите в одну общую функцию и пропускайте через неё весь вывод.
Стоит ли вместо запятой использовать табуляцию (TSV)?
Если в данных часто встречаются запятые (адреса, имена, суммы), TSV снижает частоту кавычек и упрощает визуальную проверку. Но табуляция и переносы строк в данных возможны точно так же, поэтому обработка кавычек не становится ненужной. «Это TSV, значит о разделителе можно не думать» — ошибочное рассуждение. Если с контрагентом удаётся договориться, от инцидентов лучше защищает не сам разделитель, а явная фиксация в спецификации кодировки, правил кавычек, символа переноса строки и наличия заголовка.
Если файл всё равно открывают в Excel, не лучше ли сразу выводить Excel, а не CSV?
Если главная цель — «человек смотрит и печатает в Excel», вывод в xlsx стоит рассмотреть. CSV при открытии в Excel теряет начальные нули и превращает значения в даты; полностью предотвратить это на стороне CSV нельзя. В xlsx формат ячеек задаёт сторона вывода. Если же основная цель — загрузка в другую систему, а просмотр в Excel вторичен, реалистичнее оставить CSV и в регламенте описать процедуру импорта (через функцию импорта данных).

Об авторе

Страница с профилем автора статьи.

Го Комура

Представитель KomuraSoft LLC

Специализируется на разработке программного обеспечения для Windows, техническом консалтинге и расследовании сбоев, особенно в проектах с унаследованными системами и трудно воспроизводимыми ошибками.

Публичные ссылки

Вернуться в блог