gifts2017

Чтение значений двоичных данных из файла

Опубликовал Павел Заяш (Pavl0) в раздел Программирование - Практика программирования

Иногда необходимо разобрать файл с двоичными данными. А у 1С нет инструментов для непосредственного чтения файлов. В публикации функции, которые решают эту проблему.

 Потребовалось читать в 1С данные из СКУД. Самым удобным способом было чтение из файлов-логов. Но они записаны в собственном формате, данные хранятся в двоичном виде.
У 1С нет средств для посимвольного чтения значений из файла.
В принципе, решение есть здесь: http://help1c.com/faq/view/1518.html
Но я все-таки переписал по мотивам, построил свой велосипед

 

Ниже текст функций. На выходе получаем массив, который содержит значения байт файла.

Недостатки:

  1. Чтение файла происходит целиком, поэтому возможны проблемы с памятью для достаточно больших файлов;
  2. Вероятно, есть ошибка с обработкой суффиксов == в строке BASE64. Но меня результат устроил, дальше не разбирался;
Вот здесь предложен альтернативный, гораздо более простой способ: http://infostart.ru/public/292949/

 

 

 

// Функция преобразует двоичные данные в массив целых чисел 0..255
// 
// Параметры:
//  ДвоичныеДанные  - ДвоичныеДанные - Двоичные данные, которые необходимо преобразовать в массив
//                 
Функция ДвоичныеДанные_ВМассив(Знач ДвоичныеДанные) Экспорт
	
	Утверждение_ТипСоответствует(ДвоичныеДанные,Тип("ДвоичныеДанные"));
	
	Строка64 = Base64Строка(ДвоичныеДанные);
	
	Возврат BASE64_Строка_ВМассив(Строка64);
	
КонецФункции

// По мотива кода: Гобсек http://help1c.com/faq/view/1518.html
Функция BASE64_Строка_ВМассив(Знач Строка64) Экспорт 
	
	Утверждение_ТипСоответствует(Строка64, Тип("Строка"));
	
	// Подготовить строку
	Строка64 = СтрЗаменить(Строка64, Символ(10), "");
	Строка64 = СтрЗаменить(Строка64, Символ(13), "");
	
	// Проверить длину строки
	Если СтрДлина(Строка64) % 4 <> 0 Тогда
		ВызватьИсключение "Длина строки на входе не кратна 4"; 
	КонецЕсли;
	
	// Создать соответствие символов BASE 64
	// см. http://ru.wikipedia.org/wiki/Base64
	СоответствиеСимволов = Новый Соответствие;
	сч = 0;
	Для чКод = КодСимвола("A") По КодСимвола("Z") Цикл 
		СоответствиеСимволов.Вставить(Символ(чКод), сч);
		сч = сч+1;
	КонецЦикла;
	Для чКод = КодСимвола("a") По КодСимвола("z") Цикл  
		СоответствиеСимволов.Вставить(Символ(чКод), сч);
		сч = сч+1;
	КонецЦикла;
	Для чКод = КодСимвола("0") По КодСимвола("9") Цикл 
		СоответствиеСимволов.Вставить(Символ(чКод), сч);
		сч = сч+1;
	КонецЦикла;
	СоответствиеСимволов.Вставить("+",62);
	СоответствиеСимволов.Вставить("/",63);
	// Знак "=" это спецсимвол в BASE64. Его значение равно 0
	СоответствиеСимволов.Вставить("=",0);
	//
	чКод = Неопределено;
	сч = Неопределено;

	
	// Определяем количество байт, которые кодируются
	//Если Прав(Строка64,2) = "==" Тогда
	//	КоличествоБайт = 3;
	//ИначеЕсли Прав(Строка64,1) = "=" Тогда
	//	КоличествоБайт = 2;
	//Иначе
	//	КоличествоБайт = 1;
	//КонецЕсли;
	КоличествоБайт = 3;
	Делитель = Pow(256,КоличествоБайт-1);
	МассивИзСтроки64 = Строка_ПреобразоватьВМассив(Строка64);
	МассивБайтНаВозврат = Новый Массив;
	НакопленноеЗначение = 0;
	Сч = 0;
	Для Каждого СимволСтроки64 Из МассивИзСтроки64 Цикл
		ЗначениеСимвола = СоответствиеСимволов[СимволСтроки64];
		Если ЗначениеСимвола = Неопределено Тогда
			ВызватьИсключение "Недопустимый сивол в строке BASE64: "+СимволСтроки64;
		КонецЕсли;
		НакопленноеЗначение = НакопленноеЗначение*64+ЗначениеСимвола;
		Сч = Сч+1;
				
		// Каждые четыре символа надо пересчитать в байты и обнулить накопленное значение
		Если Сч%4 = 0 Тогда
			// Определить значения байтов и записать их в массив
			// Начинаем со старшего байта, вычисляем его значение и добавляем в массив
			// Накопленную сумму при этом уменьшаем на записанное значение
			ТекущийДелитель = Делитель;
			Для НомерБайта = 1 По КоличествоБайт Цикл
				ОстатокНакопленногоЗначения = НакопленноеЗначение%ТекущийДелитель;
				МассивБайтНаВозврат.Добавить((НакопленноеЗначение-ОстатокНакопленногоЗначения)/ТекущийДелитель);
				НакопленноеЗначение = ОстатокНакопленногоЗначения;
				ТекущийДелитель = ТекущийДелитель/256;
			КонецЦикла;
			НомерБайта = Неопределено;
			ОстатокНакопленногоЗначения = Неопределено;
			ТекущийДелитель = Неопределено;
			
			// Обнулить накопленное значение
			НакопленноеЗначение = 0;
			
		КонецЕсли; // Если Сч%4 = 0 Тогда
		
	КонецЦикла;
	СимволСтроки64 = Неопределено;
	ЗначениеСимвола = Неопределено;
	НакопленноеЗначение = Неопределено;
	Сч = Неопределено;
	
	Возврат МассивБайтНаВозврат;

КонецФункции  

// Утверждение, проверяет что тип значения соответствует переданному типу
// Если не соответствует, вызывает исключение
// 
// Параметры:
//  Значение  - произвольный - значение, тип, которого необходимо проверить
// 	Тип  - Тип, которому необходимо проверить соответствие значение
//                 
Процедура Утверждение_ТипСоответствует(Значение, Тип) Экспорт
	
	Если ТипЗнч(Тип) <> Тип("Тип") Тогда
		ВызватьИсключение "Неверный тип для сравнения" ;
	КонецЕсли;
	
	Если ТипЗнч(Значение) <> Тип Тогда
		ТекстОшибки = 
			Общ.Строка_ПодставитьПараметры(
				"Не соответстует тип значения <>: <>  вместо <>",
				ТипЗнч(Значение),
				Тип,
				Значение
				);
		ВызватьИсключение ТекстОшибки;
	КонецЕсли;
	
КонецПроцедуры




.

 

 

 

См. также

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

Комментарии

1. OldthiefXXX OldthiefXXX (OldthiefXXX) 04.08.14 15:28
Где функция Строка_ПреобразоватьВМассив?????
И это что Общ.Строка_ПодставитьПараметры(
"Не соответстует тип значения <>: <> вместо <>",
ТипЗнч(Значение),
Тип,
Значение
); ?
Если делишься функцией или алгоритмом, то выкладывай полностью.
Для написания сообщения необходимо авторизоваться
Прикрепить файл
Дополнительные параметры ответа