Как объединить двоичные данные в 1С:Предприятие

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

В процессе разработки на платформе 1С:Предприятие часто возникает задача программного сложения или конкатенации двоичных данных. Это может быть необходимо при склейке нескольких PDF-документов, формировании сложных файлов для обмена с внешними системами или сборке больших архивов из частей. В этой статье мы подробно разберем, как решить эту задачу максимально эффективно, учитывая версию вашей платформы и объем обрабатываемой информации.

Метод 1: Использование штатной функции СоединитьДвоичныеДанные (для платформы 8.3.10 и выше)

Начиная с версии 8.3.10, разработчики платформы добавили наиболее простой и производительный способ решения нашей задачи. Рассмотрим его подробнее. В глобальном контексте появился метод СоединитьДвоичныеДанные, который позволяет объединить массив объектов в один за одну операцию.

Проанализируем ситуацию: у нас есть два объекта типа ДвоичныеДанные. Нам нужно получить третий объект, который будет содержать данные первого, а затем данные второго. Разберем по шагам, как это реализовать:

  1. Создадим массив и поместим в него исходные объекты.
  2. Вызовем метод платформы для объединения.

Посмотрим на пример кода:


// Предположим, у нас уже есть ДвоичныеДанные1 и ДвоичныеДанные2
МассивДляОбъединения = Новый Массив;
МассивДляОбъединения.Добавить(ДвоичныеДанные1);
МассивДляОбъединения.Добавить(ДвоичныеДанные2);

// Получаем результирующий объект
ДвоичныеДанныеРезультат = СоединитьДвоичныеДанные(МассивДляОбъединения);

Этот способ является рекомендуемым, так как он реализован на уровне ядра системы и работает быстрее всего. Важно помнить, что результирующий объект создается в оперативной памяти, поэтому для очень больших объемов данных (сотни мегабайт или гигабайты) стоит рассмотреть альтернативные методы.

Метод 2: Работа через потоки в памяти (для платформы 8.3.9 и выше)

Если вы работаете на версии платформы 8.3.9, где метод СоединитьДвоичныеДанные еще не появился, или если вам нужно выполнять более сложные манипуляции с данными (например, вставлять байты-разделители между блоками), воспользуемся механизмом потоков. Выясним причину, почему этот метод считается гибким: он позволяет работать с данными как с непрерывным потоком байтов.

Проанализируем алгоритм работы:

  1. Создаем объект ПотокВПамяти, который будет выступать в роли временного хранилища.
  2. Открываем потоки чтения для каждого из исходных объектов ДвоичныеДанные.
  3. Последовательно копируем данные из потоков чтения в наш основной поток в памяти.
  4. Закрываем основной поток и извлекаем из него итоговый результат.

Рассмотрим пример реализации:


ПотокСумма = Новый ПотокВПамяти;

// Читаем первый кусок данных и копируем в общий поток
ПотокЧтения1 = ДвоичныеДанные1.ОткрытьПотокДляЧтения();
ПотокЧтения1.КопироватьВ(ПотокСумма);
ПотокЧтения1.Закрыть();

// Читаем второй кусок данных и копируем следом
ПотокЧтения2 = ДвоичныеДанные2.ОткрытьПотокДляЧтения();
ПотокЧтения2.КопироватьВ(ПотокСумма);
ПотокЧтения2.Закрыть();

// Получаем итоговые двоичные данные
ДвоичныеДанныеСумма = ПотокСумма.ЗакрытьИПолучитьДвоичныеДанные();

Этот подход очень эффективен для управления ресурсами, так как метод КопироватьВ оптимизирован для передачи данных между потоками без лишних накладных расходов.

Метод 3: Объединение через файловую систему (для любых версий 8.x)

В ситуациях, когда объем данных настолько велик, что они не помещаются в оперативную память сервера (например, при склейке видеофайлов или огромных бэкапов), следует использовать метод ОбъединитьФайлы. Разберем по шагам, как это работает: платформа берет файлы на диске и склеивает их в новый файл, не загружая их содержимое целиком в ОЗУ.

Для этого нам сначала нужно сохранить наши ДвоичныеДанные во временные файлы. Рассмотрим пример:


// Определяем пути к временным файлам
ИмяФайла1 = ПолучитьИмяВременногоФайла();
ИмяФайла2 = ПолучитьИмяВременногоФайла();
ИмяИтоговогоФайла = ПолучитьИмяВременногоФайла();

// Сохраняем данные на диск
ДвоичныеДанные1.Записать(ИмяФайла1);
ДвоичныеДанные2.Записать(ИмяФайла2);

// Готовим массив имен файлов для объединения
МассивФайлов = Новый Массив;
МассивФайлов.Добавить(ИмяФайла1);
МассивФайлов.Добавить(ИмяФайла2);

// Выполняем объединение средствами файловой системы
ОбъединитьФайлы(МассивФайлов, ИмяИтоговогоФайла);

// Считываем результат обратно, если это необходимо
ДвоичныеДанныеРезультат = Новый ДвоичныеДанные(ИмяИтоговогоФайла);

// Не забываем удалить временные файлы
УдалитьФайлы(ИмяФайла1);
УдалитьФайлы(ИмяФайла2);
УдалитьФайлы(ИмяИтоговогоФайла);

Преимущество этого метода заключается в стабильности при работе с гигантскими объемами. Однако стоит учитывать, что операции записи и чтения с диска выполняются значительно медленнее, чем операции в оперативной памяти.

Важные замечания и антипаттерны

Рассмотрим ситуацию, которую часто допускают начинающие разработчики: попытка объединить данные через преобразование в Base64Строка. Выясним, почему так делать нельзя.

При кодировании в Base64 каждые 3 байта данных превращаются в 4 символа текста. Если размер исходных данных не кратен трем, в конце строки добавляются символы выравнивания (=). Если вы просто сложите две такие строки и попытаетесь преобразовать их обратно в двоичные данные, результат будет поврежден, так как символы выравнивания в середине итоговой строки сделают её невалидной.

Подведем итог:

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

← На главную