Потребовалось читать в 1С данные из СКУД. Самым удобным способом было чтение из файлов-логов. Но они записаны в собственном формате, данные хранятся в двоичном виде.
У 1С нет средств для посимвольного чтения значений из файла.
В принципе, решение есть здесь: http://help1c.com/faq/view/1518.html
Но я все-таки переписал по мотивам, построил свой велосипед
Ниже текст функций. На выходе получаем массив, который содержит значения байт файла.
Недостатки:
- Чтение файла происходит целиком, поэтому возможны проблемы с памятью для достаточно больших файлов;
- Вероятно, есть ошибка с обработкой суффиксов == в строке BASE64. Но меня результат устроил, дальше не разбирался;
// Функция преобразует двоичные данные в массив целых чисел 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 = Неопределено;
ЗначениеСимвола = Неопределено;
НакопленноеЗначение = Неопределено;
Сч = Неопределено;
Возврат МассивБайтНаВозврат;
КонецФункции
// Утверждение, проверяет что тип значения соответствует переданному типу
// Если не соответствует, вызывает исключение
//
// Параметры:
// Значение - произвольный - значение, тип, которого необходимо проверить
// Тип - Тип, которому необходимо проверить соответствие значение
//
Процедура Утверждение_ТипСоответствует(Значение, Тип) Экспорт
Если ТипЗнч(Тип) <> Тип("Тип") Тогда
ВызватьИсключение "Неверный тип для сравнения" ;
КонецЕсли;
Если ТипЗнч(Значение) <> Тип Тогда
ТекстОшибки =
Общ.Строка_ПодставитьПараметры(
"Не соответстует тип значения <>: <> вместо <>",
ТипЗнч(Значение),
Тип,
Значение
);
ВызватьИсключение ТекстОшибки;
КонецЕсли;
КонецПроцедуры
.