При интеграции 1С с внешними системами, например, с сайтами через API, часто возникает задача передать данные в определенной кодировке. Самый распространенный стандарт для веба — это UTF-8. Внутреннее представление строк в 1С — это UTF-16, поэтому при формировании, например, GET-запроса с кириллическими параметрами, требуется их корректно преобразовать. Разберем несколько способов, как это сделать, от простых до самых современных и правильных.
Исходная задача — пользователь вводит в 1С наименование товара, и это наименование нужно вставить в строку GET-запроса к сайту (подробнее в курсе HTTP-QUEST), предварительно перекодировав его в UTF-8.
Прежде чем переходить к решениям, давайте проясним, в каких случаях вообще требуется задумываться о кодировках. Платформа 1С берет на себя много рутинных операций, но при обмене данными с внешним миром контроль остается за разработчиком. Перекодировка строки может понадобиться в следующих ситуациях:
.txt, .csv, .xml) для обмена. Для сложной трансформации данных удобно использовать модуль «Трансформер».В нашем случае — это формирование HTTP-запроса. Посмотрим, какими инструментами мы можем решить эту задачу.
Это один из самых старых и понятных, но не самых эффективных способов. Идея проста: мы сохраняем нашу строку во временный файл в одной кодировке, а затем читаем из этого же файла, но уже указывая другую, нужную нам кодировку. Все операции по преобразованию байтов выполнит сама платформа 1С при файловых операциях.
Рассмотрим готовую функцию, которая инкапсулирует эту логику:
// Возвращает перекодированную строку
// ИсходнаяКодировка - кодировка строки, которую мы подаем на вход.
// Для стандартных строк 1С можно не указывать, но важно при чтении из внешних источников.
// КонечнаяКодировка - кодировка, которую мы хотим получить на выходе.
Функция ПерекодироватьСтрокуЧерезФайл(СтрокаДляПерекодировки, ИсходнаяКодировка = "windows-1251", КонечнаяКодировка = "UTF-8") Экспорт
ИмяВременногоФайла = ПолучитьИмяВременногоФайла("txt");
// Этап 1: Записываем строку в файл в исходной кодировке
ЗаписьТекста = Новый ЗаписьТекста;
ЗаписьТекста.Открыть(ИмяВременногоФайла, ИсходнаяКодировка);
ЗаписьТекста.Записать(СтрокаДляПерекодировки);
ЗаписьТекста.Закрыть();
// Этап 2: Читаем из этого же файла, но указываем конечную кодировку
ЧтениеТекста = Новый ЧтениеТекста(ИмяВременногоФайла, КонечнаяКодировка);
Результат = ЧтениеТекста.Прочитать();
ЧтениеТекста.Закрыть();
// Этап 3: Не забываем убрать за собой
УдалитьФайлы(ИмяВременногоФайла);
Возврат Результат;
КонецФункции // ПерекодироватьСтрокуЧерезФайл
Плюсы этого метода:
Минусы:
Этот способ можно использовать для разовых операций, но для высоконагруженных систем он не рекомендуется.
Более производительный, чем файловый, способ — использование внешнего COM-объекта Adodb.Stream. Он позволяет выполнять операции с данными в памяти, без обращения к жесткому диску. Этот метод долгое время был популярен для подобных задач.
// Перекодирует текст с использованием COM-объекта Adodb.Stream
// ВНИМАНИЕ: Этот метод будет работать только на ОС Windows.
&НаСервереБезКонтекста
Функция ПерекодироватьТекстCOM(КодируемыйТекст, НачальнаяКодировка = "utf-8", КонечнаяКодировка = "windows-1251")
Попытка
Стрим = Новый COMОбъект("Adodb.Stream");
Исключение
ВызватьИсключение "Не удалось создать COM-объект 'Adodb.Stream'. " +
"Возможно, компонент не зарегистрирован в системе или код выполняется на сервере Linux.";
КонецПопытки;
Стрим.Type = 2; // adTypeText - текстовый тип данных
Стрим.Mode = 3; // adModeReadWrite - чтение и запись
Стрим.charset = НачальнаяКодировка;
Стрим.Open();
Стрим.WriteText(КодируемыйТекст);
// Перемещаем указатель в начало потока для чтения
Стрим.Position = 0;
Стрим.charset = КонечнаяКодировка; // Устанавливаем кодировку для чтения
ПерекодированныйТекст = Стрим.ReadText(-1); // -1 = adReadAll - прочитать все
Стрим.Close();
Возврат ПерекодированныйТекст;
КонецФункции
Плюсы:
Минусы:
Это самый правильный и рекомендуемый способ перекодировки строк в современных версиях платформы 1С. Он использует встроенные объекты для работы с данными в памяти: ПотокВПамяти, ЗаписьДанных и ЧтениеТекста. Метод кроссплатформенный, быстрый и не имеет внешних зависимостей.
Логика похожа на работу с файлом, но все действия происходят в оперативной памяти.
// Перекодирует текст с использованием нативных потоков 1С
// Это наиболее универсальный и рекомендуемый способ
Функция ПерекодироватьТекст(КодируемыйТекст, НачальнаяКодировка = "windows-1251", КонечнаяКодировка = "utf-8")
// 1. Создаем поток в памяти для временного хранения данных
Поток = Новый ПотокВПамяти;
// 2. Записываем в него исходную строку, указывая ее кодировку
// Для строк, созданных внутри 1С, начальная кодировка - UTF16,
// но платформа справится с преобразованием из стандартной строки.
// Указывать начальную кодировку важно, если вы получили строку извне.
ЗаписьДанных = Новый ЗаписьДанных(Поток);
ЗаписьДанных.УстановитьКодировкуТекста(НачальнаяКодировка);
ЗаписьДанных.ЗаписатьСимволы(КодируемыйТекст);
ЗаписьДанных.Закрыть();
// 3. Получаем из потока двоичные данные
ДвоичныеДанные = Поток.ЗакрытьИПолучитьДвоичныеДанные();
// 4. Открываем поток для чтения из этих двоичных данных
ПотокЧтения = ДвоичныеДанные.ОткрытьПотокДляЧтения();
// 5. Читаем текст из потока, указывая нужную нам конечную кодировку
ЧтениеТекста = Новый ЧтениеТекста(ПотокЧтения, КонечнаяКодировка);
СтрокаВозврата = ЧтениеТекста.Прочитать();
ЧтениеТекста.Закрыть();
Возврат СтрокаВозврата;
КонецФункции
Плюсы:
Это лучший выбор для большинства задач по перекодировке.
Вернемся к нашей первоначальной задаче: нужно передать наименование товара в GET-запросе. Здесь есть важный нюанс. Просто перекодировать строку в UTF-8 недостаточно. По стандарту, URL-адреса могут содержать только ограниченный набор символов. Все остальные, включая кириллицу, пробелы и спецсимволы, должны быть представлены в специальном "процентном" виде (Percent-encoding). Например, пробел заменяется на %20, а буква "А" (кириллическая) — на %D0%90.
К счастью, для этой задачи в 1С есть специальная встроенная функция — КодироватьСтроку().
НаименованиеТовара = "Товар: Чайник 'Bosch' (красный)";
// Правильное кодирование строки для URL
ЗакодированнаяСтрока = КодироватьСтроку(НаименованиеТовара, СпособКодированияСтроки.URL);
// ЗакодированнаяСтрока будет содержать что-то вроде:
// "Товар%3A%20Чайник%20'Bosch'%20(красный)"
// (фактическое представление кириллицы будет сложнее, например %D0%A2%D0%BE%D0%B2%D0%B0%D1%80...)
// Формируем итоговый URL
АдресСервиса = "https://my-site.com/api/get_item?name=";
ИтоговыйURL = АдресСервиса + ЗакодированнаяСтрока;
Функция КодироватьСтроку с параметром СпособКодированияСтроки.URL делает именно то, что нужно: она берет исходную строку, преобразует ее символы в байты по стандарту UTF-8, а затем кодирует эти байты в процентный формат. Это самый простой, быстрый и правильный способ подготовки параметров для GET-запросов.
Давайте подведем итог и выберем правильный инструмент для каждой задачи:
КодироватьСтроку(Строка, СпособКодированияСтроки.URL).