Как быстро объединить множество строк в 1С 8.2 без функции СтрСоединить?

Программист IT и автоматизация бизнеса
← На главную

Разработчики, работающие с платформой 1С:Предприятие 8.2, часто сталкиваются с серьезным ограничением: в этой версии платформы еще отсутствует удобная и быстрая встроенная функция СтрСоединить. Когда возникает задача сформировать большой текстовый массив (например, при самостоятельной выгрузке данных в формате JSON или XML), стандартное сложение строк через оператор "+" начинает катастрофически тормозить.

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

В чем кроется проблема медленной конкатенации?

Давайте выясним физическую причину падения производительности. Когда мы пишем в цикле конструкцию вида Строка = Строка + "НовыйФрагмент", операционная система и платформа выполняют следующие действия:

  1. Вычисляется общая длина новой строки (длина левой части + длина правой части).
  2. В оперативной памяти ищется новый непрерывный свободный блок под этот размер.
  3. Происходит полное копирование старого текста (который с каждым шагом цикла становится все больше) в новый адрес памяти.
  4. В конец скопированного блока дописывается новый фрагмент.
  5. Предыдущий блок памяти помечается как свободный для сборщика мусора.

Когда итераций тысячи, а итоговый файл весит несколько мегабайт, компьютер тратит 99% времени не на полезную работу, а на постоянное выделение новых блоков RAM и гигабайты бессмысленного копирования данных туда-обратно. Процесс начинает замедляться нелинейно: если первые 1000 строк складываются мгновенно, то на 50 000 итераций система может "зависнуть" на несколько минут.

---

Решение 1. Использование объекта ЗаписьXML (Абсолютный лидер по скорости)

Самым быстрым и изящным способом в 1С 8.2, работающим исключительно в оперативной памяти (без обращения к жесткому диску), является связка объекта ЗаписьXML и метода ЗаписатьБезОбработки.

Этот метод фактически задействует внутренний низкоуровневый буфер платформы 1С (аналог класса StringBuilder в других языках программирования), который оптимизирован под сборку больших объемов текста.

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


Функция ОбъединитьСтрокиЧерезЗаписьXML(МассивСтрок)
    
    ЗаписьXML = Новый ЗаписьXML;
    // Инициализируем запись в строку (в оперативную память)
    ЗаписьXML.УстановитьСтроку();
    
    Для Каждого ТекСтрока Из МассивСтрок Цикл
        // Метод ЗаписатьБезОбработки не проверяет XML-структуру 
        // и просто вставляет текст напрямую в буфер платформы
        ЗаписьXML.ЗаписатьБезОбработки(ТекСтрока);
    КонецЦикла;
    
    // Закрываем поток и получаем готовую мегастроку
    Возврат ЗаписьXML.Закрыть();
    
КонецФункции

Почему это работает быстро? Платформа выделяет буфер памяти "с запасом" и не перевыделяет его под каждый символ. Метод ЗаписатьБезОбработки() обходит любые проверки валидности XML-тегов и не экранирует спецсимволы (такие как "<", ">" или "&"), что делает его идеальным инструментом для сборки сырого JSON-текста.

---

Решение 2. Использование объекта ТекстовыйДокумент

Еще один популярный и простой способ обойти проблему медленного сложения — использовать встроенный объект ТекстовыйДокумент. Этот объект также оптимизирован под работу с большими массивами строк.

Давайте посмотрим на программный код:


Функция ОбъединитьСтрокиЧерезТекстовыйДокумент(МассивСтрок)
    
    ТекстДок = Новый ТекстовыйДокумент;
    Для Каждого ТекСтрока Из МассивСтрок Цикл
        ТекстДок.ДобавитьСтроку(ТекСтрока);
    КонецЦикла;
    
    Возврат ТекстДок.ПолучитьТекст();  
    
КонецФункции

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

Внимание! Никогда не пытайтесь убрать эти переносы через СтрЗаменить(Результат, Символы.ПС, ""). На больших объемах операция СтрЗаменить полностью уничтожит весь выигрыш в скорости, так как она заново запустит тяжелый процесс перевыделения памяти под многомегабайтный текст.

---

Решение 3. Каскадное сложение (Буферизация в памяти)

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

Суть идеи проста: вместо того чтобы постоянно прибавлять маленькие строчки к огромной итоговой строке, мы сначала собираем маленькие фрагменты в промежуточный буфер среднего размера. Когда этот буфер заполняется, мы один раз прибавляем его к основной строке и очищаем.

Давайте проанализируем реализацию такого алгоритма:


Функция ОбъединитьСтрокиСБуферизацией(МассивСтрок)
    
    ИтоговаяСтрока = "";
    ВременныйБуфер = "";
    
    // Опытным путем установлено, что оптимальный размер буфера - около 10-20 Кб
    ЛимитБуфера = 15000; 
    
    Для Каждого ТекСтрока Из МассивСтрок Цикл
        
        ВременныйБуфер = ВременныйБуфер + ТекСтрока;
        
        Если СтрДлина(ВременныйБуфер) > ЛимитБуфера Тогда
            ИтоговаяСтрока = ИтоговаяСтрока + ВременныйБуфер;
            ВременныйБуфер = "";
        КонецЕсли;
        
    КонецЦикла;
    
    // Дописываем остаток из буфера
    ИтоговаяСтрока = ИтоговаяСтрока + ВременныйБуфер;
    
    Возврат ИтоговаяСтрока;
    
КонецФункции

Этот способ уступает по скорости ЗаписьXML, но он работает в разы быстрее, чем классическое последовательное сложение элементов "в лоб".

---

Решение 4. Использование COM-объекта ADODB.Stream (Для работы без лишних спецсимволов)

Если вам требуется максимальная скорость работы в оперативной памяти Windows-сервера без добавления мусорных символов переноса строк, можно прибегнуть к возможностям операционной системы через технологию COM.

Объект ADODB.Stream позволяет открыть поток в памяти, быстро записать туда данные и прочитать готовый результат.


Функция ОбъединитьСтрокиЧерезADODB(МассивСтрок)
    
    Поток = Новый COMОбъект("ADODB.Stream");
    Поток.Type = 2; // Указываем текстовый режим работы
    Поток.Charset = "utf-8";
    Поток.Open();
    
    Для Каждого ТекСтрока Из МассивСтрок Цикл
        Поток.WriteText(ТекСтрока);
    КонецЦикла;
    
    // Сбрасываем курсор в начало потока для чтения
    Поток.Position = 0;
    Результат = Поток.ReadText();
    Поток.Close();
    
    Возврат Результат;
    
КонецФункции

Преимущества: Полное отсутствие сторонних символов разделителей и высочайшая скорость сборки, сравнимая с низкоуровневыми библиотеками.

---

Сравнение производительности и рекомендации

Давайте подведем итог и определимся, какой метод выбрать для вашей практической задачи в 1С 8.2:

Используя предложенные методики, вы сможете ускорить выгрузку тяжелых пакетов данных в вашей базе 1С 8.2 с нескольких минут до долей секунды!

← На главную