В процессе разработки на платформе 1С:Предприятие часто возникает задача программного сложения или конкатенации двоичных данных. Это может быть необходимо при склейке нескольких PDF-документов, формировании сложных файлов для обмена с внешними системами или сборке больших архивов из частей. В этой статье мы подробно разберем, как решить эту задачу максимально эффективно, учитывая версию вашей платформы и объем обрабатываемой информации.
Начиная с версии 8.3.10, разработчики платформы добавили наиболее простой и производительный способ решения нашей задачи. Рассмотрим его подробнее. В глобальном контексте появился метод СоединитьДвоичныеДанные, который позволяет объединить массив объектов в один за одну операцию.
Проанализируем ситуацию: у нас есть два объекта типа ДвоичныеДанные. Нам нужно получить третий объект, который будет содержать данные первого, а затем данные второго. Разберем по шагам, как это реализовать:
Посмотрим на пример кода:
// Предположим, у нас уже есть ДвоичныеДанные1 и ДвоичныеДанные2
МассивДляОбъединения = Новый Массив;
МассивДляОбъединения.Добавить(ДвоичныеДанные1);
МассивДляОбъединения.Добавить(ДвоичныеДанные2);
// Получаем результирующий объект
ДвоичныеДанныеРезультат = СоединитьДвоичныеДанные(МассивДляОбъединения);
Этот способ является рекомендуемым, так как он реализован на уровне ядра системы и работает быстрее всего. Важно помнить, что результирующий объект создается в оперативной памяти, поэтому для очень больших объемов данных (сотни мегабайт или гигабайты) стоит рассмотреть альтернативные методы.
Если вы работаете на версии платформы 8.3.9, где метод СоединитьДвоичныеДанные еще не появился, или если вам нужно выполнять более сложные манипуляции с данными (например, вставлять байты-разделители между блоками), воспользуемся механизмом потоков. Выясним причину, почему этот метод считается гибким: он позволяет работать с данными как с непрерывным потоком байтов.
Проанализируем алгоритм работы:
ПотокВПамяти, который будет выступать в роли временного хранилища.ДвоичныеДанные.Рассмотрим пример реализации:
ПотокСумма = Новый ПотокВПамяти;
// Читаем первый кусок данных и копируем в общий поток
ПотокЧтения1 = ДвоичныеДанные1.ОткрытьПотокДляЧтения();
ПотокЧтения1.КопироватьВ(ПотокСумма);
ПотокЧтения1.Закрыть();
// Читаем второй кусок данных и копируем следом
ПотокЧтения2 = ДвоичныеДанные2.ОткрытьПотокДляЧтения();
ПотокЧтения2.КопироватьВ(ПотокСумма);
ПотокЧтения2.Закрыть();
// Получаем итоговые двоичные данные
ДвоичныеДанныеСумма = ПотокСумма.ЗакрытьИПолучитьДвоичныеДанные();
Этот подход очень эффективен для управления ресурсами, так как метод КопироватьВ оптимизирован для передачи данных между потоками без лишних накладных расходов.
В ситуациях, когда объем данных настолько велик, что они не помещаются в оперативную память сервера (например, при склейке видеофайлов или огромных бэкапов), следует использовать метод ОбъединитьФайлы. Разберем по шагам, как это работает: платформа берет файлы на диске и склеивает их в новый файл, не загружая их содержимое целиком в ОЗУ.
Для этого нам сначала нужно сохранить наши ДвоичныеДанные во временные файлы. Рассмотрим пример:
// Определяем пути к временным файлам
ИмяФайла1 = ПолучитьИмяВременногоФайла();
ИмяФайла2 = ПолучитьИмяВременногоФайла();
ИмяИтоговогоФайла = ПолучитьИмяВременногоФайла();
// Сохраняем данные на диск
ДвоичныеДанные1.Записать(ИмяФайла1);
ДвоичныеДанные2.Записать(ИмяФайла2);
// Готовим массив имен файлов для объединения
МассивФайлов = Новый Массив;
МассивФайлов.Добавить(ИмяФайла1);
МассивФайлов.Добавить(ИмяФайла2);
// Выполняем объединение средствами файловой системы
ОбъединитьФайлы(МассивФайлов, ИмяИтоговогоФайла);
// Считываем результат обратно, если это необходимо
ДвоичныеДанныеРезультат = Новый ДвоичныеДанные(ИмяИтоговогоФайла);
// Не забываем удалить временные файлы
УдалитьФайлы(ИмяФайла1);
УдалитьФайлы(ИмяФайла2);
УдалитьФайлы(ИмяИтоговогоФайла);
Преимущество этого метода заключается в стабильности при работе с гигантскими объемами. Однако стоит учитывать, что операции записи и чтения с диска выполняются значительно медленнее, чем операции в оперативной памяти.
Рассмотрим ситуацию, которую часто допускают начинающие разработчики: попытка объединить данные через преобразование в Base64Строка. Выясним, почему так делать нельзя.
При кодировании в Base64 каждые 3 байта данных превращаются в 4 символа текста. Если размер исходных данных не кратен трем, в конце строки добавляются символы выравнивания (=). Если вы просто сложите две такие строки и попытаетесь преобразовать их обратно в двоичные данные, результат будет поврежден, так как символы выравнивания в середине итоговой строки сделают её невалидной.
Подведем итог:
СоединитьДвоичныеДанные.ПотокВПамяти и объект ЗаписьДанных.ОбъединитьФайлы.Используя эти методы, вы обеспечите высокую скорость работы вашего кода и стабильность системы при обработке любых объемов двоичной информации.