gifts2017

Двоичные данные и кодировка Base64 в 1С 8.Х

Опубликовал Жан-Эстер ван Гобсек (Гобсек) в раздел Программирование - Практика программирования

Как преобразовать строку, закодированную при помощи алгоритма Base64, в массив байтов и обратно

Двоичные данные и кодировка Base64 в 1С 8.Х

Считать данные из двоичного файла можно при помощи функции ДвоичныеДанные(ИмяФайла). Например:

ДД = ДвоичныеДанные(ИмяФайла);

Здесть ДД - специальный объект, который называется "двоичные данные".
В языке 1С есть функция, которая преобразует двоичные данные в строку Base64Строка(ДвоичныеДанные). Например:

Строка64 = Base64Строка(ДвоичныеДанные);

Здесь Строка64 - обычная строка, с которой можно делать все, что угодно.
В конце статьи приведена функция Преобразовать64(Строка64 = неопределено, Массив64 = неопределено),  которая преобразовывает строку в массив байтов, и обратно.
Для того, чтобы получить массив байтов из строки, вызываем ее так:

Массив64 = Преобразовать64(Строка64 , );

Для обратного преобразования вызываем так:

Строка64 = Преобразовать64( , Массив64 );

Про алгоритм кодировки Base64 см.: 
http://ru.wikipedia.org/wiki/Base64

http://habrahabr.ru/post/190054/

Преобразовать строку в двоичные данные можно при помощи функции Base64Значение(Строка64).

Все указанные функции, кроме Преобразовать64, являются встроенными функциям платформы.

 

Далее листинг функции Преобразовать64.

&НаСервере
Функция Преобразовать64(Строка64 = неопределено, Массив64 = неопределено)
 Таб64 = Новый ТаблицаЗначений;
 Таб64.Колонки.Добавить("Код");
 Таб64.Колонки.Добавить("Символ");
 Нпп = 0;
 Для Код = КодСимвола("A") По КодСимвола("Z") Цикл
  стр = Таб64.Добавить();
  стр.Код = Нпп;
  стр.Символ = Символ(Код);
  Нпп = Нпп + 1;
 КонецЦикла;
 Для Код = КодСимвола("a") По КодСимвола("z") Цикл
  стр = Таб64.Добавить();
  стр.Код = Нпп;
  стр.Символ = Символ(Код);
  Нпп = Нпп + 1;
 КонецЦикла;
 стр = Таб64.Добавить();
 стр.Код = Нпп;
 стр.Символ = "0";
 Нпп = Нпп + 1;
 Для Код = 1 По 9 Цикл
  стр = Таб64.Добавить();
  стр.Код = Нпп;
  стр.Символ = Формат(Код,"ЧЦ=1; ЧДЦ=0");
  Нпп = Нпп + 1;
 КонецЦикла;
 стр = Таб64.Добавить();
 стр.Код = Нпп;
 стр.Символ = "+";
 Нпп = Нпп + 1;
 стр = Таб64.Добавить();
 стр.Код = Нпп;
 стр.Символ = "/";
 
 Если Массив64 = неопределено Тогда 
  Если Строка64 = неопределено Тогда
   Сообщить("неверный вызов функции");
   Возврат неопределено;
  КонецЕсли;
  //Уберем переносы строк
  Строка64 = СтрЗаменить(Строка64, Символ(10), "");
  Строка64 = СтрЗаменить(Строка64, Символ(13), "");
  
  //преобразовываем строку в массив
  Если СтрДлина(Строка64) % 4 <> 0 Тогда
   Сообщить("длина строки на входе должна быть кратна 4"); 
   Сообщить(СтрДлина(Строка64)); 
   Возврат неопределено;
  КонецЕсли;
  Кол4 = Цел(СтрДлина(Строка64) / 4);
  РазмерМ = Кол4 * 3;
  Если Прав(Строка64, 2) = "==" Тогда
   РазмерМ = РазмерМ - 2;
  ИначеЕсли Прав(Строка64, 1) = "=" Тогда
   РазмерМ = РазмерМ - 1;
  КонецЕсли;   
  Массив64 = Новый Массив(РазмерМ);
  Для А = 1 По Кол4 Цикл
   Число3 = 0;
   Для Б = 1 По 4 Цикл
    Буква1 = Сред(Строка64, (А-1)*4 + Б, 1); 
    Если Буква1 = "=" Тогда
     Код4 = 0;
    Иначе
     стрН = Таб64.Найти(Буква1, "Символ");
     Если стрН = Неопределено Тогда
      Сообщить("ошибка при поиске "+ КодСимвола(Буква1)); 
     Иначе 
      Код4 = стрН.Код;
     КонецЕсли;
    КонецЕсли;
    Число3 = Число3 * 64 + Код4;
   КонецЦикла;
   Ост = Число3 % 256;
   Индекс = (А-1)*3 + 2;
   Если Индекс <= РазмерМ - 1 Тогда
    Массив64[Индекс] = Ост;
   КонецЕсли;
   Число3 = (Число3 - Ост) / 256;
   Ост = Число3 % 256;
   Индекс = (А-1)*3 + 1;
   Если Индекс <= РазмерМ - 1 Тогда
    Массив64[Индекс] = Ост;
   КонецЕсли;
   Число3 = (Число3 - Ост) / 256;
   Ост = Число3 % 256;
   Массив64[(А-1)*3 + 0] = Ост;
  КонецЦикла;
  Возврат Массив64;
 Иначе //Преобразовываем массив в строку
  Строка64 = "";
  Кол3 = Цел(Массив64.Количество() / 3);
  Если Массив64.Количество() % 3 <> 0 Тогда
   Кол3 = Кол3 + 1;
  КонецЕсли;
  Для А = 1 По Кол3 Цикл
   Число3 = Массив64[(А-1)*3]; 
   Если (А-1)*3+1 <= Массив64.ВГраница() Тогда
    Код3 = Массив64[(А-1)*3+1];
   Иначе
    Код3 = 0;
   КонецЕсли;
   Число3 = Число3*256 + Код3;
   Если (А-1)*3+2 <= Массив64.ВГраница() Тогда
    Код3 = Массив64[(А-1)*3+2];
   Иначе
    Код3 = 0;
   КонецЕсли;
   Число3 = Число3*256 + Код3;
   
   Ост4 = Число3 % 64;
   Число3 = (Число3 - Ост4) / 64;
   Ост3 = Число3 % 64;
   Число3 = (Число3 - Ост3) / 64;
   Ост2 = Число3 % 64;
   Число3 = (Число3 - Ост2) / 64;
   Ост1 = Число3 % 64;
   Число3 = (Число3 - Ост1) / 64;
   стрН = Таб64.Найти(Ост1, "Код");
   Если стрН = неопределено Тогда
    Сообщить("Ошибка при поиске");
   Иначе
    Строка64 = Строка64 + стрН.Символ;
   КонецЕсли;
   стрН = Таб64.Найти(Ост2, "Код");
   Если стрН = неопределено Тогда
    Сообщить("Ошибка при поиске");
   Иначе
    Строка64 = Строка64 + стрН.Символ;
   КонецЕсли;
   стрН = Таб64.Найти(Ост3, "Код");
   Если стрН = неопределено Тогда
    Сообщить("Ошибка при поиске");
   Иначе
    Строка64 = Строка64 + стрН.Символ;
   КонецЕсли;
   стрН = Таб64.Найти(Ост4, "Код");
   Если стрН = неопределено Тогда
    Сообщить("Ошибка при поиске");
   Иначе
    Строка64 = Строка64 + стрН.Символ;
   КонецЕсли;
  КонецЦикла;
  //Если количество символов не делится на 3, то на конце должны быть
  //знаки "="
  Если Массив64.Количество() % 3 = 1 Тогда
   Строка64 = Лев(Строка64, СтрДлина(Строка64)-2)+ "=="; 
  ИначеЕсли Массив64.Количество() % 3 = 2 Тогда
   Строка64 = Лев(Строка64, СтрДлина(Строка64)-1)+ "="; 
  КонецЕсли;
  Возврат Строка64;
 КонецЕсли;
КонецФункции

См. также

Подписаться Добавить вознаграждение

Комментарии

1. Гость 22.01.14 08:26
Автор, на ошибки проверяли?
2. andrewks 22.01.14 08:29
для кого/чего эта статья? или чисто учебные цели - демонстрация реализации алгоритма кодирования base64 на языке 1с?
3. lefthander (lefthander) 22.01.14 09:28
А на рубрику обратили внимание? Правильно, практика программирования - вполне уместно.
Спасибо автору.
4. Жан-Эстер ван Гобсек (Гобсек) 22.01.14 10:30
(1) Гость,
Процедура рабочая
5. Жан-Эстер ван Гобсек (Гобсек) 22.01.14 10:36
(2) andrewks,

Мне понадобилась такая процедура для перекодировки. К своему удивлению, готовой на языке 1С в Интернете я не нашел. Написал свою. Сегодня на одном из форумов увидел, что один из участников спрашивал про такую процедуру. Я выложил сюда. Кому надо, пусть пользуются.
6. Владимир Нет (tusv) 22.01.14 10:38
Отрывок кода
Если Индекс Массив64[Индекс] = Ост;
КонецЕсли;

Что это?
7. Гость 22.01.14 10:41
извините, вот это мне не понятно.

Если Индекс Массив64[Индекс] = Ост;
КонецЕсли;
8. Жан-Эстер ван Гобсек (Гобсек) 22.01.14 11:55
(6) tusv,
(7)Гость
Видимо, копирование-вставка прошли некорректно. Сейчас думаю, то ли править статью, то ли выложить внешнюю обработку. Или в виде эксперимента выложить листинг в комментарий и посмотреть, корректно ли он скопируется.
9. Жан-Эстер ван Гобсек (Гобсек) 22.01.14 11:56
Выкладываю листинг в комментарий:
&НаСервере
Функция Преобразовать64(Строка64 = неопределено, Массив64 = неопределено)
	Таб64 = Новый ТаблицаЗначений;
	Таб64.Колонки.Добавить("Код");
	Таб64.Колонки.Добавить("Символ");
	Нпп = 0;
	Для Код = КодСимвола("A") По КодСимвола("Z") Цикл
		стр = Таб64.Добавить();
		стр.Код = Нпп;
		стр.Символ = Символ(Код);
		Нпп = Нпп + 1;
	КонецЦикла;
	Для Код = КодСимвола("a") По КодСимвола("z") Цикл
		стр = Таб64.Добавить();
		стр.Код = Нпп;
		стр.Символ = Символ(Код);
		Нпп = Нпп + 1;
	КонецЦикла;
	стр = Таб64.Добавить();
	стр.Код = Нпп;
	стр.Символ = "0";
	Нпп = Нпп + 1;
	Для Код = 1 По 9 Цикл
		стр = Таб64.Добавить();
		стр.Код = Нпп;
		стр.Символ = Формат(Код,"ЧЦ=1; ЧДЦ=0");
		Нпп = Нпп + 1;
	КонецЦикла;
	стр = Таб64.Добавить();
	стр.Код = Нпп;
	стр.Символ = "+";
	Нпп = Нпп + 1;
	стр = Таб64.Добавить();
	стр.Код = Нпп;
	стр.Символ = "/";
	
	Если Массив64 = неопределено Тогда 
		Если Строка64 = неопределено Тогда
			Сообщить("неверный вызов функции");
			Возврат неопределено;
		КонецЕсли;
		//Уберем переносы строк
		Строка64 = СтрЗаменить(Строка64, Символ(10), "");
		Строка64 = СтрЗаменить(Строка64, Символ(13), "");
		
		//преобразовываем строку в массив
		Если СтрДлина(Строка64) % 4 <> 0 Тогда
			Сообщить("длина строки на входе должна быть кратна 4"); 
			Сообщить(СтрДлина(Строка64)); 
			Возврат неопределено;
		КонецЕсли;
		Кол4 = Цел(СтрДлина(Строка64) / 4);
		РазмерМ = Кол4 * 3;
		Если Прав(Строка64, 2) = "==" Тогда
			РазмерМ = РазмерМ - 2;
		ИначеЕсли Прав(Строка64, 1) = "=" Тогда
			РазмерМ = РазмерМ - 1;
		КонецЕсли;			
		Массив64 = Новый Массив(РазмерМ);
		Для А = 1 По Кол4 Цикл
			Число3 = 0;
			Для Б = 1 По 4 Цикл
				Буква1 = Сред(Строка64, (А-1)*4 + Б, 1);	
				Если Буква1 = "=" Тогда
					Код4 = 0;
				Иначе
					стрН = Таб64.Найти(Буква1, "Символ");
					Если стрН = Неопределено Тогда
						Сообщить("ошибка при поиске "+ КодСимвола(Буква1));	
					Иначе 
						Код4 = стрН.Код;
					КонецЕсли;
				КонецЕсли;
				Число3 = Число3 * 64 + Код4;
			КонецЦикла;
			Ост = Число3 % 256;
			Индекс = (А-1)*3 + 2;
			Если Индекс <= РазмерМ - 1 Тогда
				Массив64[Индекс] = Ост;
			КонецЕсли;
			Число3 = (Число3 - Ост) / 256;
			Ост = Число3 % 256;
			Индекс = (А-1)*3 + 1;
			Если Индекс <= РазмерМ - 1 Тогда
				Массив64[Индекс] = Ост;
			КонецЕсли;
			Число3 = (Число3 - Ост) / 256;
			Ост = Число3 % 256;
			Массив64[(А-1)*3 + 0] = Ост;
		КонецЦикла;
		Возврат Массив64;
	Иначе //Преобразовываем массив в строку
		Строка64 = "";
		Кол3 = Цел(Массив64.Количество() / 3);
		Если Массив64.Количество() % 3 <> 0 Тогда
			Кол3 = Кол3 + 1;
		КонецЕсли;
		Для А = 1 По Кол3 Цикл
			Число3 = Массив64[(А-1)*3];	
			Если (А-1)*3+1 <= Массив64.ВГраница() Тогда
				Код3 = Массив64[(А-1)*3+1];
			Иначе
				Код3 = 0;
			КонецЕсли;
			Число3 = Число3*256 + Код3;
			Если (А-1)*3+2 <= Массив64.ВГраница() Тогда
				Код3 = Массив64[(А-1)*3+2];
			Иначе
				Код3 = 0;
			КонецЕсли;
			Число3 = Число3*256 + Код3;
			
			Ост4 = Число3 % 64;
			Число3 = (Число3 - Ост4) / 64;
			Ост3 = Число3 % 64;
			Число3 = (Число3 - Ост3) / 64;
			Ост2 = Число3 % 64;
			Число3 = (Число3 - Ост2) / 64;
			Ост1 = Число3 % 64;
			Число3 = (Число3 - Ост1) / 64;
			стрН = Таб64.Найти(Ост1, "Код");
			Если стрН = неопределено Тогда
				Сообщить("Ошибка при поиске");
			Иначе
				Строка64 = Строка64 + стрН.Символ;
			КонецЕсли;
			стрН = Таб64.Найти(Ост2, "Код");
			Если стрН = неопределено Тогда
				Сообщить("Ошибка при поиске");
			Иначе
				Строка64 = Строка64 + стрН.Символ;
			КонецЕсли;
			стрН = Таб64.Найти(Ост3, "Код");
			Если стрН = неопределено Тогда
				Сообщить("Ошибка при поиске");
			Иначе
				Строка64 = Строка64 + стрН.Символ;
			КонецЕсли;
			стрН = Таб64.Найти(Ост4, "Код");
			Если стрН = неопределено Тогда
				Сообщить("Ошибка при поиске");
			Иначе
				Строка64 = Строка64 + стрН.Символ;
			КонецЕсли;
		КонецЦикла;
		//Если количество символов не делится на 3, то на конце должны быть
		//знаки "="
		Если Массив64.Количество() % 3 = 1 Тогда
			Строка64 = Лев(Строка64, СтрДлина(Строка64)-2)+ "==";	
		ИначеЕсли Массив64.Количество() % 3 = 2 Тогда
			Строка64 = Лев(Строка64, СтрДлина(Строка64)-1)+ "=";	
		КонецЕсли;
		Возврат Строка64;
	КонецЕсли;
КонецФункции
...Показать Скрыть
10. Жан-Эстер ван Гобсек (Гобсек) 22.01.14 11:58
Выкладываю обработку. Там только листинг процедуры.
Прикрепленные файлы:
Проба64.epf
11. andrewks 22.01.14 12:29
(5) Гобсек,
Мне понадобилась такая процедура для перекодировки.

для перекодировки чего? мне непонятна практическая цель.

если цель - демонстрация реалтизации алгоритма, тогда без вопросов
12. Жан-Эстер ван Гобсек (Гобсек) 22.01.14 12:36
Статью переделал. Теперь вроде все нормально.
13. Жан-Эстер ван Гобсек (Гобсек) 22.01.14 12:44
(11)Практическая задача: банк присылает файлы *.DBF Их содержимое нужно загружать в 1С. Для того, чтобы стандартно обработать файл при помощи объекта XBASE, нужно сначала снять электронную подпись. Программное обеспечение для электронных подписей на данном компьютере ставить не планируется. Делаем так. Из заголовка файла узнаем какая у него должна быть длина. Если фактическая длина больше на заданное число байт, то конец файла обрезаем. Для реализации схемы нужно работать с двоичными данными. Все достаточно просто. Вопрос возник только с перекодировкой Base64 туда и обратно.
14. andrewks 22.01.14 13:13
(13) Гобсек, т.е. Вам нужно ДД (двоичные данные) обрезать, и сохранить в файл, я правильно понял? а для чего, собственно, Массив?
15. DENIS SUKHOV (miap) 22.01.14 13:20
Внешнюю обработку, конечно, надо. а то код разбросан уже по коментам, неудобно. Если б я не прочел коменты, не догадался бы.
16. Жан-Эстер ван Гобсек (Гобсек) 22.01.14 13:21
(14)Чтобы проанализировать заголовок DBF файла.
17. Жан-Эстер ван Гобсек (Гобсек) 22.01.14 13:24
(15)Я статью уже исправил. Теперь вроде все нормально. Код процедуры можно взять из статьи.
18. andrewks 22.01.14 13:30
(16) Гобсек, ага, ясно.
т.е. берёте размер из заголовка и просто отсекаете подпись, которая идёт в самом конце файла.

задача, конечно, извращённая :)

а точно длина подписи не постоянна?
19. Жан-Эстер ван Гобсек (Гобсек) 22.01.14 13:36
(18)Зато никаких внешних компонент и тому подобное. Не нужно держать в голове, что на данном компьютере должно быть установлено для нормальной работы.
Длина подписи постоянна. Но нужно проверить, она есть или ее нету.
20. Александр Гладких (yku) 25.01.14 21:52
(11), (13) Приведу еще один пример.
Дано: базы ЗУП и БП на скуле.
Справочник физ. лица синхронизирован по ссылке.
В ЗУПе есть внешний источник данных - справочник физ. лиц из БП.
Нужно, находясь в ЗУПе получить данные по конкретному физ лицу из БП.
Но ссылки во внешнем источнике данных имеют тип Binary(16).
Т.е. нам нужно преобразовать уникальный идентификатор в двоичные данные.
Алгоритм такой
УникальныйИдентификатор -> "51012ccc-397d-11de-b595-00055d80a2b9" -> "b59500055d80a2b911de397d51012ccc" -> Числовой массив из шестнадцати байтов -> СтрокаBase64 -> ДвоичныеДанные -> Запрос "Где Внеш_ФизЛица.Ссылка = &ДвоичныеДанные"

PS:
-> ???? -> PROFIT!!!
21. Dima (sokir) 22.09.14 12:35
(20) yku, не понял как из "51012ccc-397d-11de-b595-00055d80a2b9" получено "b59500055d80a2b911de397d51012ccc". Можно поподробнее?
22. Алексей Белоусов (AllexSoft) 21.11.14 13:52
(20) yku, весе просто, переверните "51012ccc-397d-11de-b595-00055d80a2b9" и удалите "-" и все поймете
23. uri1978 uri1978 (uri1978) 25.05.16 17:48
Строка64 - обычная строка

Работает только с английским алфавитом и цифрами...
24. Евгений (Sevg) 23.06.16 16:20
Пример моего кода
новКартБМП=Новый Картинка(QRkod);
HEXСтрокаКартинка=СтрЗаменить(""+новКартБМП.ПолучитьДвоичныеДанные()," ","");
и анализировать вроде быстрее HEXстроку
25. Алексей Дмухин (AlexeyDmuhin) 25.07.16 10:41
Спасибо за функцию Преобразовать64!

я с ее помощью получаю хэш-строку в base64 :)

Функция ВычислитьНаСервереХешСтрокиПоАлгоритму_HMAC_SHA256(Строка, Ключ, ВернутьBase64 = Истина) Экспорт
	
	Текст = Новый COMОбъект("System.Text.UTF8Encoding");
	КриптоSHA256 = Новый COMОбъект("System.Security.Cryptography.HMACSHA256");
	КриптоSHA256.key = Текст.GetBytes_4(Ключ);
	Если ВернутьBase64 Тогда
		
		Хэш256 = КриптоSHA256.ComputeHash_2(Текст.GetBytes_4(Строка)).Выгрузить();
		СтрокаХэша = Преобразовать64(, Хэш256);
		
	Иначе	
		
		Хэш256 = КриптоSHA256.ComputeHash_2(Текст.GetBytes_4(Строка));
		оStr = Новый COMОбъект("System.Text.StringBuilder");
		Для Каждого стр Из Хэш256 Цикл
		    оStr.AppendFormat("{0:x02}", стр);
		КонецЦикла;

		СтрокаХэша = оStr.ToString; //последовательность байтов
		
	КонецЕсли;
		
	Возврат СтрокаХэша;
	
КонецФункции
...Показать Скрыть


до этого считал на Jawa-скрипте через MSScriptControl, но траблы и их решение при переводе на 64-bit сервер не устроили
Для написания сообщения необходимо авторизоваться
Прикрепить файл
Дополнительные параметры ответа