При интеграции систем 1С с веб-сайтами (например, при обмене заказами или каталогами товаров) разработчики часто сталкиваются с проблемой, когда текстовые данные на русском языке загружаются некорректно. Вместо понятных названий и реквизитов в систему попадают «кракозябры» вида "ДатаФорРмыйР". При этом на самом сайте и даже при открытии файла через обычный текстовый блокнот в Windows всё отображается отлично.
В этой статье мы подробно разберем, почему возникает эта ошибка, как устроены механизмы кодирования текста в разных средах и рассмотрим несколько вариантов решения проблемы — от быстрого исправления «в лоб» до архитектурно правильных подходов с использованием встроенных объектов платформы 1С:Предприятие.
Основная причина появления нечитаемых символов — несовпадение кодировки, в которой файл был записан на веб-сервере, и кодировки, которую платформа 1С использует для чтения по умолчанию. Кириллический текст на современных веб-ресурсах практически всегда формируется в кодировке UTF-8. В то же время операционная система Windows в русскоязычной локализации и объект 1С ТекстовыйДокумент по умолчанию пытаются прочесть текстовые файлы в кодировке Windows-1251 (ANSI).
В кодировке UTF-8 каждый символ русского алфавита кодируется двумя байтами, а в Windows-1251 — одним байтом. Когда 1С считывает двухбайтовые символы UTF-8, предполагая, что это однобайтовая кодировка Windows-1251, она интерпретирует каждый отдельный байт как самостоятельный символ. Именно из-за этого русская буква «Д» превращается в два непонятных знака, образуя характерные «кракозябры».
Возникает логичный вопрос: почему файлы, созданные самой 1С, читаются нормально? Дело в специальной сигнатуре, которая называется BOM (Byte Order Mark).
ТекстовыйДокумент по умолчанию добавляет в самое начало файла маркер BOM (последовательность байтов EF BB BF). При последующем чтении этого файла платформа видит этот маркер и безошибочно определяет кодировку как UTF-8.Рассмотрим фрагмент кода, из-за которого часто возникает данная проблема:
ФайлXML = Новый ТекстовыйДокумент;
ФайлXML.Прочитать(Параметры.ФайлЗагрузки);
СтрокаXML = ФайлXML.ПолучитьТекст();
Использование объекта ТекстовыйДокумент для работы с XML-структурами крайне нежелательно по следующим причинам:
Ниже мы разберем правильные варианты решения этой задачи.
Если вам необходимо временно сохранить текущую логику работы с объектом ТекстовыйДокумент, достаточно явно передать кодировку во втором параметре метода Прочитать(). Платформа перестанет пытаться угадать кодировку по BOM-маркеру и принудительно применит UTF-8.
Проанализируем исправленный вариант кода:
ФайлXML = Новый ТекстовыйДокумент;
// Явно указываем кодировку UTF-8 во втором параметре метода
ФайлXML.Прочитать(Параметры.ФайлЗагрузки, КодировкаТекста.UTF8);
СтрокаXML = ФайлXML.ПолучитьТекст();
После добавления системного перечисления КодировкаТекста.UTF8 файлы без BOM-маркера начнут считываться корректно, и кириллица примет нормальный вид.
Для правильной и производительной работы с XML-документами в платформе 1С предусмотрен специализированный объект — ЧтениеXML. Он работает по принципу последовательного потокового чтения (аналог SAX-парсера) и обладает встроенными механизмами автоматического распознавания кодировок.
Посмотрим на пример правильной реализации:
ЧтениеФайлаXML = Новый ЧтениеXML;
// Объект самостоятельно проанализирует заголовок xml-файла и определит кодировку
ЧтениеФайлаXML.ОткрытьФайл(Параметры.ФайлЗагрузки);
Пока ЧтениеФайлаXML.Прочитать() Цикл
// Здесь выполняется потоковый разбор узлов XML-документа
Если ЧтениеФайлаXML.ТипУзла = ТипУзлаXML.НачалоЭлемента Тогда
ИмяУзла = ЧтениеФайлаXML.Имя;
// Обрабатываем данные узла
КонецЕсли;
КонецЦикла;
ЧтениеФайлаXML.Закрыть();
Почему этот способ является приоритетным:
ЧтениеXML при инициализации файла считывает самую первую строку (декларацию XML), например: <?xml version="1.0" encoding="UTF-8"?>. Он извлекает значение атрибута encoding и автоматически переводит весь процесс чтения в нужный формат, независимо от наличия или отсутствия BOM-маркера. Разработчику больше не нужно вручную прописывать кодировки.Если перед вами стоит задача прочесть файл именно как обычную текстовую строку (без разбора XML-структуры), в современных версиях платформы 1С:Предприятие 8.3 реализованы более эффективные альтернативы устаревшему объекту ТекстовыйДокумент.
Вариант А. Использование объекта ЧтениеТекста
Этот объект спроектирован специально для неинтерактивного программного чтения текстовых файлов. Он работает быстрее и потребляет значительно меньше ресурсов:
ПутьКФайлу = Параметры.ФайлЗагрузки;
ФайлЧтения = Новый ЧтениеТекста(ПутьКФайлу, КодировкаТекста.UTF8);
СтрокаXML = ФайлЧтения.Прочитать();
ФайлЧтения.Закрыть();
Вариант Б. Чтение через ДвоичныеДанные (для версий 1С 8.3.10 и выше)
Для быстрого и безопасного преобразования файлов в строку без риска возникновения проблем с BOM-маркерами можно использовать методы работы с двоичными данными:
ПутьКФайлу = Параметры.ФайлЗагрузки;
ДвоичныеДанныеФайла = Новый ДвоичныеДанные(ПутьКФайлу);
// Преобразуем двоичные данные напрямую в строку с указанием кодировки UTF-8
СтрокаXML = ПолучитьСтрокуИзДвоичныхДанных(ДвоичныеДанныеФайла, КодировкаТекста.UTF8);
Этот метод работает чрезвычайно быстро на уровне платформы и исключает любые ошибки интерпретации байтов.
Если же вам в будущем понадобится записать текстовый файл для отправки на сайт строго в формате UTF-8 без BOM, вы можете использовать метод обратного преобразования с отключением вывода BOM-маркера:
ДвоичныеДанныеДляЗаписи = ПолучитьДвоичныеДанныеИзСтроки(СтрокаXML, КодировкаТекста.UTF8, Ложь);
ДвоичныеДанныеДляЗаписи.Записать(ПутьКФайлу);
Параметр Ложь в функции ПолучитьДвоичныеДанныеИзСтроки гарантирует, что в начале файла не будет лишней сигнатуры BOM, и веб-сервер примет файл без каких-либо ошибок парсинга.
Для предотвращения ошибок кодировки при интеграции 1С с веб-ресурсами придерживайтесь следующих правил:
ЧтениеXML, так как он самостоятельно считывает кодировку из декларации файла.ЧтениеТекста или функцию ПолучитьСтрокуИзДвоичныхДанных с явным указанием кодировки КодировкаТекста.UTF8.ТекстовыйДокумент в программном коде для чтения внешних файлов обмена во избежание чрезмерного потребления оперативной памяти и ошибок распознавания кириллицы.