Как программно получить размер папки в 1С:Предприятие

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

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

Метод 1: Использование встроенной функции НайтиФайлы

Самый универсальный и кроссплатформенный способ, который будет работать как на Windows, так и на Linux — это использование объекта Файл и метода НайтиФайлы. Платформа 1С предоставляет мощный инструментарий для работы с файловой системой, который позволяет получить список всех объектов в каталоге. Рассмотрим подробнее, как реализовать суммирование размеров файлов.

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


Функция ПолучитьРазмерПапки(ПутьККаталогу) Экспорт
    
    ПеременнаяРазмер = 0;
    
    // Получаем массив файлов, используя маску "*.*"
    // Третий параметр Истина указывает на необходимость рекурсивного поиска во вложенных папках
    МассивФайлов = НайтиФайлы(ПутьККаталогу, "*.*", Истина);
    
    Для Каждого ТекущийФайл Из МассивФайлов Цикл
        // Проверяем, является ли объект файлом, так как НайтиФайлы возвращает и каталоги
        Если ТекущийФайл.ЭтоФайл() Тогда
            ПеременнаяРазмер = ПеременнаяРазмер + ТекущийФайл.Размер();
        КонецЕсли;
    КонецЦикла;
    
    Возврат ПеременнаяРазмер; // Размер возвращается в байтах
    
КонецФункции

Проанализируем ситуацию: метод НайтиФайлы с параметром рекурсии удобен, но при работе с очень большими структурами папок (десятки тысяч файлов) он может потреблять значительный объем оперативной памяти, так как сначала формирует полный массив объектов в памяти, а только потом позволяет начать их обход. Если вы столкнулись с ограничением памяти, посмотрим на пример рекурсивного обхода вручную.

Метод 2: Ручной рекурсивный обход каталогов

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

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

Функция РассчитатьРазмерРекурсивно(Путь) Экспорт
    ОбщийРазмер = 0;
    НайденныеОбъекты = НайтиФайлы(Путь, "*.*", Ложь);
    
    Для Каждого Объект Из НайденныеОбъекты Цикл
        Если Объект.ЭтоФайл() Тогда
            ОбщийРазмер = ОбщийРазмер + Объект.Размер();
        ИначеЕсли Объект.ЭтоКаталог() Тогда
            // Рекурсивный вызов для вложенной папки
            ОбщийРазмер = ОбщийРазмер + РассчитатьРазмерРекурсивно(Объект.ПолноеИмя);
        КонецЕсли;
    КонецЦикла;
    
    Возврат ОбщийРазмер;
КонецФункции

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

Метод 3: Использование COM-объекта Scripting.FileSystemObject (только для Windows)

Если ваша база данных 1С работает под управлением операционной системы Windows, рассмотрим возможность использования системного объекта Scripting.FileSystemObject (FSO). Этот метод зачастую работает быстрее встроенных средств 1С, так как обращается напрямую к системным библиотекам оптимизированным для работы с NTFS/FAT32.

Проанализируем код для работы с COM-объектом:


Функция ПолучитьРазмерЧерезFSO(ПутьКПапке)
    
    Попытка
        FSO = Новый COMОбъект("Scripting.FileSystemObject");
        ОбъектПапка = FSO.GetFolder(ПутьКПапке);
        // Свойство Size объекта Folder возвращает размер всех файлов и подпапок
        Возврат ОбъектПапка.Size;
    Исключение
        ЗаписьЖурналаРегистрации("Ошибка получения размера папки", УровеньЖурналаРегистрации.Ошибка,,, ОписаниеОшибки());
        Возврат 0;
    КонецПопытки;
    
КонецФункции

Использование Scripting.FileSystemObject позволяет получить размер папки одной строкой кода без необходимости циклического обхода. Однако выясним причину, по которой этот метод не всегда применим: он требует наличия соответствующих прав доступа и не работает на серверах под управлением Linux или в веб-клиенте без установки специальных расширений. Также стоит учитывать, что при обращении к Size операционная система всё равно выполняет сканирование содержимого, поэтому для очень больших каталогов возможна задержка исполнения кода.

Сравнение методов и практические советы

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

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


Функция ФорматироватьРазмер(РазмерВБайтах)
    Если РазмерВБайтах < 1024 Тогда
        Возврат Строка(РазмерВБайтах) + " байт";
    ИначеЕсли РазмерВБайтах < (1024 * 1024) Тогда
        Возврат Строка(Окр(РазмерВБайтах / 1024, 2)) + " Кб";
    ИначеЕсли РазмерВБайтах < (1024 * 1024 * 1024) Тогда
        Возврат Строка(Окр(РазмерВБайтах / 1024 / 1024, 2)) + " Мб";
    Иначе
        Возврат Строка(Окр(РазмерВБайтах / 1024 / 1024 / 1024, 2)) + " Гб";
    КонецЕсли;
КонецФункции

В завершение разберем вопросы безопасности. При работе с файловой системой всегда используйте блок Попытка...Исключение. У программы 1С (особенно если код выполняется на стороне сервера) может не быть прав на чтение определенных подкаталогов. В таком случае встроенные функции могут вызвать ошибку доступа, которую необходимо корректно обработать, чтобы не прерывать выполнение всего алгоритма.

Таким образом, мы проанализировали три различных подхода к определению размера каталога. Выбор конкретного метода зависит от архитектуры вашей системы и требований к производительности. Рекомендуется использовать встроенные средства платформы НайтиФайлы как наиболее надежные и поддерживаемые вендором.

← На главную