Борьба с unicode в 1С

Unicode и 1С.

Работая над обработкой «Работа с картами 4 в 1» столкнулся с интересной ситуацией. Геокодинг Рамблера возвращал результат в виде

…»\u041c\u043e\u0441\u043a\u0432\u0430″…

Немного погуглив я узнал, что это переданы буквы кириллицы в формате unicode. Приведенное слово — это «Москва». Поскольку 1С не сильно дружит с этим форматом и читать его очень просто, я решил написать функции для перекодировки. Что из этого получилось смотрите далее.

u041c — це ASCII-код кирилличного символа «М» в 16-ричной системе. Значит для декодировки надо

  • Вытащить из сроки все «буквы» — они начинаются на «u» и содержат только цифры 16-ричной системы — для этого используем регулярные выражения
  • Вытащить из буквы 16-ричное число — то есть все символы после буквы «u»
  • Конвертировать его в 10-ричную систему — получить ASCII-код символа
  • Получить символ по его ASCII-кода

Предлагаю вашему вниманию код, реализующий все выше описанное.

UnicodeEncode()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
//Функция декодирует полученный unicod текст - из ответа геокодера Рамблера
// в привычный нам
//Параметры:
// Строка
//Возвращаемое значение:
// Строка
Функция UnicodeEncode(Строка) Экспорт
    Результат = Истина;
 
    Попытка
        //регулярное выражение
        Рег = Новый COMОбъект("VBScript.RegExp");
        Рег.IgnoreCase = Истина;
        Рег.Global = Истина;
        Рег.Multiline = Ложь;
        Рег.Pattern = "u[0-9a-f]+";
        Колекция = Рег.Execute(Строка);
        Для Каждого Элемент Из Колекция Цикл
            Если СтрДЛина(Элемент.value) = 1 Тогда
                Продолжить;
            КонецЕсли;        
 
            КодСимвола = ПереводЧислаИз16в10(Сред(ВРег(Элемент.value), 2));
            Символ = Символ(КодСимвола);
            Строка = СтрЗаменить(Строка, "\" + Элемент.value, Символ);
        КонецЦикла;    
    Исключение
        Результат = Ложь;
        Сообщить("Ошибка преобразования из Unicode", СтатусСообщения.Информация);
    КонецПопытки;
 
    Возврат Результат;
КонецФункции
///////конец

ПереводЧислаИз16в10()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
Функция ПереводЧислаИз16в10(Знач Значение)
	Результат = 0;
 
	//перевод значения в строку
	Если ТипЗнч(Значение) <> Тип("Строка") Тогда
		Значение = СокрЛП(Строка(Значение));
	КонецЕсли;
 
	МаксРазрядЦелых = 0;
	МаксРазрядЦелых = СтрДлина(Значение) - 1;
 
	н = МаксРазрядЦелых;
	Ин = 1;
	Пока н >= 0 Цикл
		ТекЗначение = СтруктураЧисел.Получить(Сред(Значение, Ин, 1)) * Pow(16, н);
		Результат = Результат + ТекЗначение;
		н = н - 1;
		Ин = Ин + 1;
	КонецЦикла;
 
	Возврат Результат;
КонецФункции
///////конец

Также необходимо перед началом инициализировать структуру соответствия 16-летним числам 10-летним. Я это сделал в модуле объекта, но вы можете его реализовать где угодно.

Инициализация структуры чисел

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
Перем СтруктураЧисел;
//////основной блок модуля
СтруктураЧисел = Новый Соответствие;
СтруктураЧисел.Вставить("0", 0);
СтруктураЧисел.Вставить("1", 1);
СтруктураЧисел.Вставить("2", 2);
СтруктураЧисел.Вставить("3", 3);
СтруктураЧисел.Вставить("4", 4);
СтруктураЧисел.Вставить("5", 5);
СтруктураЧисел.Вставить("6", 6);
СтруктураЧисел.Вставить("7", 7);
СтруктураЧисел.Вставить("8", 8);
СтруктураЧисел.Вставить("9", 9);
СтруктураЧисел.Вставить("A", 10);
СтруктураЧисел.Вставить("B", 11);
СтруктураЧисел.Вставить("C", 12);
СтруктураЧисел.Вставить("D", 13);
СтруктураЧисел.Вставить("E", 14);
СтруктураЧисел.Вставить("F", 15);
///////конец


Сразу же скажу, что функцию декодирования я взял из нета. С какого точно ресурса — не помню (пусть автор уже простит), поэтому на авторство претендую.
Пользуйтесь.