Почему при выгрузке данных в CSV из 1С вместо русских букв появляются знаки вопроса и как это исправить

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

При программной выгрузке данных в текстовые форматы разработчики нередко сталкиваются с ситуацией, когда готовый файл при открытии в блокноте или табличном редакторе отображает знаки вопроса («???») вместо кириллицы. Разберем механизм возникновения этой ошибки и выясним, как правильно управлять кодировками при формировании файлов формата CSV средствами платформы 1С:Предприятие.

Выясним причину такого поведения. Вопросительные знаки в тексте свидетельствуют о том, что данные были безвозвратно искажены именно в момент создания и записи файла, а не при его открытии. Рассмотрим исходный фрагмент кода, который приводит к подобной ошибке:


Функция ЗаписатьCSV(Текст, ИмяФайла)
    Кодировка = КодировкаТекста.ANSI;
    ТекстовыйФайлЗапись = Новый ЗаписьТекста(ИмяФайла, Кодировка);
    ТекстовыйФайлЗапись.ЗаписатьСтроку(Текст);
    ТекстовыйФайлЗапись.Закрыть();
    Возврат 0;
КонецФункции

Проанализируем работу свойства КодировкаТекста.ANSI. Данное перечисление сообщает платформе, что нужно использовать системную кодовую страницу операционной системы по умолчанию (Active Code Page). Если код выгрузки выполняется на стороне сервера (директива &НаСервере) под управлением Windows с англоязычной локалью по умолчанию (например, windows-1252) или на сервере под управлением Linux, кириллические символы в активной кодовой таблице отсутствуют. При попытке преобразовать строку Юникод в однобайтную таблицу операционная система заменяет все неизвестные ей символы байтом 0x3F, то есть знаком вопроса. В результате исходные данные утрачиваются навсегда.

Способ 1. Принудительное указание кодировки windows-1251 строковым параметром

Если принимающая сторона требует однобайтовую кодировку Windows (кириллица), нельзя полагаться на системное значение КодировкаТекста.ANSI. Конструктор объекта ЗаписьТекста вторым параметром принимает не только предопределенные элементы перечисления, но и точное строковое обозначение необходимой кодовой страницы.

Посмотрим на пример выгрузки с явным заданием кодировки windows-1251:


Функция ЗаписатьCSVВКодировке1251(Текст, ИмяФайла)
    // Явно указываем кодировку строкой для исключения зависимости от настроек сервера
    ТекстовыйФайлЗапись = Новый ЗаписьТекста(ИмяФайла, "windows-1251");
    ТекстовыйФайлЗапись.ЗаписатьСтроку(Текст);
    ТекстовыйФайлЗапись.Закрыть();
КонецФункции

В этом случае платформа принудительно преобразует символы по таблице windows-1251 независимо от региональных настроек сервера или операционной системы пользователя.

Способ 2. Выгрузка в формате UTF-8

Современным стандартом обмена данными является использование Юникода. Платформа 1С поддерживает запись файлов в кодировке UTF-8. Рассмотрим, как применить это решение на практике:


Функция ЗаписатьCSVВКодировкеUTF8(Текст, ИмяФайла)
    Кодировка = КодировкаТекста.UTF8;
    ТекстовыйФайлЗапись = Новый ЗаписьТекста(ИмяФайла, Кодировка);
    ТекстовыйФайлЗапись.ЗаписатьСтроку(Текст);
    ТекстовыйФайлЗапись.Закрыть();
КонецФункции

Разберем важный нюанс при использовании КодировкаТекста.UTF8 с объектом ЗаписьТекста:

  1. Запись маркера BOM: По умолчанию ЗаписьТекста добавляет в самое начало файла специальный трехбайтовый маркер последовательности байтов — BOM (Byte Order Mark, EF BB BF).
  2. Совместимость с Excel: Для открытия CSV-файла в Microsoft Excel маркер BOM необходим. Без него Excel открывает CSV в кодировке по умолчанию операционной системы, что снова превратит текст в нечитаемые символы («кракозябры»).
  3. Совместимость с внешними сервисами: Некоторые внешние учетные системы, утилиты командной строки Linux или парсеры баз данных не поддерживают наличие BOM и выдают ошибку при разборе первой строки заголовка.

Способ 3. Выгрузка в UTF-8 без маркера последовательности байтов (без BOM)

Если для интеграции требуется строгий формат UTF-8 без BOM, объект ЗаписьТекста не позволяет отключить его запись напрямую. В таком случае воспользуемся альтернативным платформенным механизмом преобразования строки в двоичные данные:


Процедура ЗаписатьCSVБезBOM(Текст, ИмяФайла)
    // Четвертый параметр (Ложь) отключает добавление метки порядка байтов (BOM)
    ДвоичныеДанные = ПолучитьДвоичныеДанныеИзСтроки(Текст, КодировкаТекста.UTF8, ПорядокБайтов.Прямой, Ложь);
    ДвоичныеДанные.Записать(ИмяФайла);
КонецПроцедуры

Способ 4. Формирование CSV через другие платформенные объекты

Рассмотрим альтернативные способы формирования файлов CSV, если ручное построчное наполнение через ЗаписьТекста не требуется:

  1. Объект ТекстовыйДокумент: Позволяет быстро записать накопленный текстовый массив с явным заданием нужной кодировки:
    
    ТекстДок = Новый ТекстовыйДокумент;
    ТекстДок.УстановитьТекст(Текст);
    ТекстДок.Записать(ИмяФайла, "windows-1251");
    
  2. Объект ТабличныйДокумент: Если отчет или данные выгрузки уже выводятся в табличную форму, их можно сохранить в CSV без ручного перебора ячеек: ТабДок.Записать(ИмяФайла, ТипФайлаТабличногоДокумента.CSV);

Рекомендации по формированию корректного CSV

При выгрузке текстовых файлов обратим внимание на следующие технические детали:

  1. Разделители строк: В объекте ЗаписьТекста третий параметр конструктора задает разделитель строк. По умолчанию он зависит от операционной системы. Для кроссплатформенной надежности и корректного чтения в Excel рекомендуется явно передавать стандартный разделитель Символы.ВК + Символы.ПС (CRLF).
  2. Экранирование символов: Согласно спецификации формата CSV, если значение колонки содержит разделитель полей (точку с запятой, запятую), символ перевода строки или кавычку, значение должно быть заключено в двойные кавычки, а внутренние кавычки в значении удвоены ("").
← На главную