К статье
Практический материал

Разработка и Конфигурация · 12 мин

Как прочитать файлы из каталога в 1С

Как прочитать файлы из каталога в 1С: методы НайтиФайлы и НайтиФайлыАсинх, фильтры по маске, обход подкаталогов, проверка результатов и типичные ошибки.

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

Важно понимать ключевое ограничение: код, работающий с файловой системой, выполняется там, где он запущен. Если процедура выполняется на сервере, каталог ищется на дисках сервера 1С, а не на компьютере пользователя. Это самая частая причина ситуации «на моём компьютере работает, а в проде — нет».

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

Метод НайтиФайлы: базовый синтаксис

Метод НайтиФайлы доступен и на клиенте, и на сервере. Он принимает три параметра: путь к каталогу, маска поиска и признак поиска в подкаталогах. Минимальный вариант — один параметр, путь к папке:

НайденныеФайлы = НайтиФайлы("D:\Обмен\Выписки");

Для Каждого Файл Из НайденныеФайлы Цикл

Сообщить(Файл.ПолноеИмя);

КонецЦикла;

Если каталог не существует, метод не вызывает исключение — он просто возвращает пустой массив. Поэтому проверку существования папки нужно делать отдельно, иначе вы не отличите «папки нет» от «папка пустая»:

Каталог = Новый Файл("D:\Обмен\Выписки");

Если Не Каталог.Существует() Тогда

ВызватьИсключение "Каталог обмена не найден: D:\Обмен\Выписки";

КонецЕсли;

Каждый элемент массива — объект типа «Файл» с полезными свойствами: ПолноеИмя, Имя, ИмяБезРасширения, Расширение, Путь, Размер(), ПолучитьВремяИзменения(), а также методы ЭтоКаталог() и ЭтоФайл(). Этого достаточно, чтобы отфильтровать нужное уже после поиска.

Фильтрация по маске и расширению

Второй параметр — маска имени файла. Поддерживаются стандартные подстановочные символы: * — любая последовательность символов, ? — один произвольный символ. Чтобы получить только XML-файлы выписок:

НайденныеФайлы = НайтиФайлы("D:\Обмен\Выписки", "*.xml");

Маска сравнивается без учёта регистра на Windows, но на Linux регистр может иметь значение — это зависит от файловой системы. Если обмен идёт через Linux-сервер, надёжнее искать по широкой маске и проверять расширение в коде:

Для Каждого Файл Из НайденныеФайлы Цикл

Если НРег(Файл.Расширение) <> ".xml" Тогда

Продолжить;

КонецЕсли;

// обработка файла

КонецЦикла;

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

Обход подкаталогов и сортировка по дате

Третий параметр — булево «искать в подкаталогах». Со значением Истина метод рекурсивно обходит всё дерево папок:

НайденныеФайлы = НайтиФайлы("D:\Архив", "*.pdf", Истина);

Рекурсивный поиск по большому дереву (сотни тысяч файлов, сетевой диск) может занимать заметное время и блокировать сеанс. Если структура папок известна — например, «Год\Месяц\файлы» — эффективнее обходить каталоги явно, контролируя глубину и обрабатывая файлы порциями.

Типовая задача — взять только самый свежий файл (последняя выгрузка из банка). Для этого массив перебирается с сравнением времени изменения:

ПоследнийФайл = Неопределено;

Для Каждого Файл Из НайденныеФайлы Цикл

Если Не Файл.ЭтоФайл() Тогда

Продолжить;

КонецЕсли;

Если ПоследнийФайл = Неопределено

Или Файл.ПолучитьВремяИзменения() > ПоследнийФайл.ПолучитьВремяИзменения() Тогда

ПоследнийФайл = Файл;

КонецЕсли;

КонецЦикла;

Порядок действий для типовой загрузки
  1. 1
    Проверьте существование каталога через объект Файл и метод Существует()
  2. 2
    Вызовите НайтиФайлы с путём, маской и признаком поиска в подкаталогах
  3. 3
    Отфильтруйте результат: ЭтоФайл(), расширение, дата изменения
  4. 4
    Прочитайте содержимое каждого файла подходящим читателем (ЧтениеТекста, ЧтениеXML, ЧтениеДанных)
  5. 5
    После успешной загрузки переместите файл в архивную папку, чтобы не обработать его повторно

Чтение содержимого найденных файлов

НайтиФайлы возвращает только описания файлов, а не их содержимое. Дальше файл открывается подходящим объектом в зависимости от формата. Для текстовых файлов используется ЧтениеТекста:

Чтение = Новый ЧтениеТекста(Файл.ПолноеИмя, КодировкаТекста.UTF8);

Текст = Чтение.Прочитать();

Чтение.Закрыть();

Для XML — ЧтениеXML с последовательным перебором узлов, для двоичных данных (картинки, PDF) — ЧтениеДанных или помещение файла во временное хранилище через НачатьПомещениеФайла на клиенте. Кодировку текстового файла нужно знать заранее: банковские выписки нередко приходят в ANSI (windows-1251), и чтение их как UTF-8 даст нечитаемые символы.

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

1c
Файлы = НайтиФайлы(ПутьККаталогу, "*.xml", Ложь);
Для Каждого Файл Из Файлы Цикл
    Если Файл.ЭтоФайл() Тогда
        Чтение = Новый ЧтениеТекста(Файл.ПолноеИмя, КодировкаТекста.UTF8);
        Содержимое = Чтение.Прочитать();
        Чтение.Закрыть();
    КонецЕсли;
КонецЦикла;

Асинхронный вариант: НайтиФайлыАсинх

В тонком и веб-клиенте синхронные вызовы файловой системы либо запрещены режимом использования модальности, либо требуют расширения работы с файлами. Современный подход — асинхронный метод НайтиФайлыАсинх с описанием оповещения:

Оповещение = Новый ОписаниеОповещения("ПослеПоискаФайлов", ЭтотОбъект);

НачатьНайтиФайлы(Оповещение, "D:\Обмен", "*.xml", Истина);

Результат приходит в процедуру, указанную в оповещении, где первым параметром передаётся тот же массив объектов «Файл». Логика обработки внутри не отличается от синхронного варианта — меняется только способ получения массива.

Асинхронные методы требуют, чтобы у пользователя было установлено расширение работы с файлами (в веб-клиенте) или разрешён доступ к файловой системе. Если расширение не установлено, платформа предложит установить его — предусмотрите эту ветку в обработке, иначе пользователь увидит немую ошибку.

Клиент или сервер: где выполнять поиск

Выбор места выполнения определяет, чей диск будет прочитан. Серверный вызов видит только диски и сетевые пути, доступные учётной записи, под которой работает агент сервера 1С (обычно это служебная учётная запись, а не пользователь). Клиентский вызов видит диски конкретного пользователя.

Для регламентных заданий (автоматический разбор папки обмена по расписанию) подходит только сервер: регламентные задания выполняются на сервере и не имеют клиентского контекста. Путь к папке обмена при этом должен быть сетевым (вида \\server\share) и доступным учётной записи агента — локальный путь D:\Обмен будет указывать на диск самого сервера.

Сравнение вариантов

НайтиФайлы на сервере

Подходит для регламентных заданий и фоновой обработки. Ограничение: видит только диски сервера и сетевые пути, доступные учётной записи агента 1С.

НайтиФайлы на толстом клиенте

Подходит для интерактивной работы с локальными папками пользователя. Ограничение: не работает в тонком и веб-клиенте без расширения.

НачатьНайтиФайлы (асинхронно)

Единственный корректный вариант для тонкого и веб-клиента. Требует расширения работы с файлами и перестройки кода на оповещения.

Чтение каталога через FTP/HTTP

Подходит, когда папка находится на удалённом ресурсе. Ограничение: нужен отдельный код обмена, НайтиФайлы здесь не применяется.

Типичные ошибки и ограничения

Первая и самая массовая ошибка — поиск на сервере по пути, который существует только на клиенте. Код «работает у разработчика» в файловой базе (где клиент и сервер — один компьютер) и перестаёт работать в клиент-серверном варианте. Проверяйте, где физически находится каталог.

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

Третья группа проблем — обработка неполностью записанных файлов. Если внешняя система кладёт файл в папку, а 1С его тут же подхватывает, можно прочитать обрезанный файл. Надёжные приёмы: дожидаться, пока размер файла перестанет меняться, либо принимать файлы с временным расширением (.tmp), которое отправитель переименовывает после полной записи.

Типичные ошибки
01
Поиск по локальному пути на сервере — каталог ищется на диске сервера, результат пустой
02
Отсутствие проверки ЭтоФайл() — попытка прочитать подкаталог как файл завершается исключением
03
Чтение файла в неверной кодировке — данные загружаются с нечитаемыми символами вместо кириллицы
04
Повторная обработка одних и тех же файлов — после загрузки файлы не перемещаются в архив и не помечаются
05
Захват недозаписанного файла — обмен ломается на обрезанных данных внешней системы

Проверка результата и FAQ

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

Контрольные точки

Как проверить результат

Массив после НайтиФайлы
Норма

Содержит ожидаемое число объектов Файл

Тревожный признак

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

Содержимое прочитанного файла
Норма

Текст читается, кириллица отображается корректно

Тревожный признак

Кракозябры — неверная кодировка; обрезанные данные — файл был недописан

Повторный запуск обработки
Норма

Уже загруженные файлы пропускаются

Тревожный признак

Данные задваиваются — нет архивирования или учёта обработанных файлов

Как получить только файлы, без подкаталогов?

Отфильтруйте массив после НайтиФайлы: в цикле проверяйте Файл.ЭтоФайл() и пропускайте элементы, для которых оно возвращает Ложь. Отдельного параметра «только файлы» у метода нет.

Почему НайтиФайлы возвращает пустой массив, хотя файлы в папке есть?

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

Как прочитать файлы из сетевой папки?

Укажите UNC-путь вида \\сервер\ресурс\папка. Для серверного выполнения сетевой ресурс должен быть доступен учётной записи агента сервера 1С — подключённый сетевой диск пользователя сервер не увидит.

Можно ли искать по нескольким расширениям сразу?

Одним вызовом — нет, маска одна. Либо вызывайте НайтиФайлы несколько раз и объединяйте массивы, либо ищите по маске . и проверяйте расширение в цикле. Второй способ быстрее на больших каталогах.

Как обработать только новые файлы, не трогая старые?

Сравнивайте время изменения файла с датой последнего запуска, которую храните в константе или регистре, либо перемещайте обработанные файлы в архивный подкаталог. Второй способ надёжнее, так как не зависит от корректности дат.

Работает ли НайтиФайлы в веб-клиенте?

Синхронный вызов — нет. Используйте НачатьНайтиФайлы с описанием оповещения и установленным расширением работы с файлами в браузере. Без расширения доступ к локальной файловой системе из веб-клиента невозможен.

Итог

Что важно запомнить

Файлы из каталога читаются методом НайтиФайлы с путём, маской и признаком обхода подкаталогов; результат — массив объектов «Файл», который нужно фильтвать через ЭтоФайл() и расширение. Код на сервере видит только диски сервера, для тонкого и веб-клиента используйте асинхронный НачатьНайтиФайлы. После загрузки перемещайте файлы в архив и журналируйте результат — это защищает от дублей и упрощает диагностику.