Боротьба з 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);
///////конец

Зразу ж вкажу, що функцію декодування я взяв з інета. З якого точно ресурсу – не пам’ятаю (хай автор вже вибачає), тому на авторство претендую.
Користуйтесь.