Как быстро склеить множество текстовых файлов в один в среде 1С 7.7

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

В процессе разработки на платформе 1С 7.7 программисты часто сталкиваются с задачей обработки больших массивов текстовых данных. Типичный сценарий — объединение тысяч мелких файлов (логов, протоколов расчетов, временных дампов) в один финальный документ. Стандартный объект Текст, встроенный в платформу, при попытке выполнить такую операцию «в лоб» через циклы ДобавитьСтроку() начинает работать крайне медленно. Это происходит из-за особенностей управления памятью в 1С 7.7: чем больше становится итоговый объект, тем дольше занимает каждая следующая вставка, так как системе приходится постоянно перераспределять адресное пространство.

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

Анализ проблемы: почему штатный метод работает медленно

Рассмотрим классический код, который обычно использует начинающий разработчик для склейки файлов. Проанализируем ситуацию на примере кода из обсуждения:


ТекущийКаталог = ФС.ТекКаталог();
ФС.УстТекКаталог(ВыбКаталог);
Тлог = СоздатьОбъект("Текст"); 
сч = 0;
ИмяФайла = ФС.НайтиПервыйФайл("~*.tmp");
Пока ПустаяСтрока(ИмяФайла) = 0 Цикл 
    сч = сч + 1; 
    Тчасть = СоздатьОбъект("Текст");
    Тчасть.Открыть(ВыбКаталог+ИмяФайла); 
    КС = Тчасть.КоличествоСтрок(); 
    Для ы = 1 По КС Цикл 
        Тлог.ДобавитьСтроку(Тчасть.ПолучитьСтроку(ы)); 
    КонецЦикла;
    ИмяФайла = ФС.НайтиСледующийФайл();
КонецЦикла;
Тлог.Записать(ВыбКаталог + "All.txt");

Основные причины тормозов здесь следующие:

  1. Построчное чтение и запись: Каждая итерация цикла Для вызывает метод ПолучитьСтроку и ДобавитьСтроку. При наличии миллионов строк суммарные накладные расходы на вызов методов объекта становятся критическими.
  2. Переполнение памяти: Объект Текст хранит все данные в оперативной памяти. При достижении объема в десятки мегабайт 1С начинает испытывать трудности с выделением непрерывных блоков памяти, что может привести к зависанию или аварийному завершению программы.
  3. Избыточное обновление интерфейса: Использование функции Состояние() внутри цикла также замедляет процесс, так как отрисовка статус-бара требует ресурсов процессора.

Решение №1: Использование командной строки Windows (самый быстрый способ)

Самый эффективный способ склеить файлы — делегировать эту задачу операционной системе. Команда COPY работает на уровне файловой системы и потоков ввода-вывода, игнорируя логику интерпретатора 1С.

Для простой склейки всех файлов в каталоге можно использовать следующую команду:


КомандаСистемы("copy /b " + ПутьККаталогу + "*.tmp " + ПутьККаталогу + "result.txt");

Важные нюансы использования CMD:

Рассмотрим пример генерации бат-файла для строгого контроля последовательности:


ТекстБата = СоздатьОбъект("Текст");
ИмяФайла = ФС.НайтиПервыйФайл(ВыбКаталог + "*.tmp");
ТекстБата.ДобавитьСтроку("del Combined.txt"); // Удаляем старый результат
Пока ПустаяСтрока(ИмяФайла) = 0 Цикл
    // Используем >> для добавления в конец файла
    ТекстБата.ДобавитьСтроку("type " + ИмяФайла + " >> Combined.txt");
    ИмяФайла = ФС.НайтиСледующийФайл();
КонецЦикла;
ТекстБата.Записать(ВыбКаталог + "merge.bat");
КомандаСистемы(ВыбКаталог + "merge.bat");

Решение №2: Гибкая склейка через PowerShell

Если требуется предварительная сортировка (например, по дате создания) или фильтрация содержимого, отличным инструментом станет PowerShell. Он позволяет выполнять сложные операции в одну строку.

Проанализируем пример команды для склейки с сортировкой по дате:


КомандаСистемы("powershell -Command ""Get-ChildItem -Path 'C:\Logs\' -Filter *.log | Sort-Object CreationTime | Get-Content | Out-File 'C:\Logs\Total.txt'""");

Однако помните, что стандартный Get-Content в PowerShell работает довольно медленно на огромных файлах, так как оборачивает каждую строку в объект. Для файлов объемом в сотни мегабайт лучше использовать методы .NET напрямую:


$files = Get-ChildItem "C:\Logs\*.log" | Sort-Object LastWriteTime;
[System.IO.File]::WriteAllLines("C:\Logs\Result.txt", (foreach ($f in $files) { [System.IO.File]::ReadAllLines($f.FullName) }));

Решение №3: Программный доступ через FileSystemObject (FSO)

Если вы не хотите зависеть от внешних командных интерпретаторов и вам нужно контролировать процесс внутри 1С, используйте объект Scripting.FileSystemObject. Выясним, как сделать это правильно, избегая метода ReadAll.

Вызов ReadAll() для файла в 50 МБ мгновенно «съест» 50 МБ оперативной памяти. Правильнее читать файлы блоками. Рассмотрим пример реализации:


ФСО = СоздатьОбъект("Scripting.FileSystemObject");
ВыходнойФайл = ФСО.CreateTextFile("C:\All.txt", -1); // -1 для создания в Unicode, 0 для ANSI

// Допустим, у нас есть список имен файлов в СпискеЗначений
Для Ном = 1 По СписокФайлов.РазмерСписка() Цикл
    ПутьКФайлу = СписокФайлов.ПолучитьЗначение(Ном);
    Если ФСО.FileExists(ПутьКФайлу) = 1 Тогда
        ФайлИст = ФСО.OpenTextFile(ПутьКФайлу, 1); // 1 = ForReading
        Пока ФайлИст.AtEndOfStream = 0 Цикл
            // Читаем блоками по 128 КБ для скорости
            ВыходнойФайл.Write(ФайлИст.Read(131072));
        КонецЦикла;
        ФайлИст.Close();
    КонецЕсли;
КонецЦикла;
ВыходнойФайл.Close();

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

Решение №4: ADODB.Stream для бинарной склейки и разных кодировок

Объект ADODB.Stream является наиболее мощным средством для работы с потоками. Он позволяет легко менять кодировки (например, склеить файлы Windows-1251 и сохранить их в UTF-8) и работать с бинарными данными без искажений.

Рассмотрим алгоритм работы со стримом:

  1. Создаем основной поток (Stream) в памяти или с привязкой к файлу.
  2. Поочередно открываем каждый исходный файл во втором (временном) потоке.
  3. Копируем содержимое временного потока в основной методом CopyTo.
  4. Сохраняем результат на диск.

Метод CopyTo работает на уровне системных вызовов копирования памяти, что обеспечивает максимальную производительность, сопоставимую с командой copy /b.

Советы по оптимизации логирования

Если задача склейки файлов возникает регулярно из-за того, что ваша система генерирует слишком много логов, стоит рассмотреть архитектурные изменения:

Подводя итог, можно сказать: если вам нужно максимально быстро и просто соединить файлы «здесь и сейчас», используйте КомандаСистемы с вызовом copy /b. Если же требуется сложная логика обработки в процессе склейки — выбирайте FileSystemObject с блочным чтением.

← На главную