При разработке внешних обработок, отчетов или механизмов выгрузки/загрузки данных программисты 1С часто сталкиваются с необходимостью определить каталог, в котором находится рабочий файл. Стандартный метод ПолучитьИспользуемоеИмяФайла() возвращает полный путь, например: "C:\MyFolder\SubFolder\ExternalDataProcessor.epf". Но что делать, если вам нужно получить только путь к папке "C:\MyFolder\SubFolder\", чтобы сохранить туда лог-файл, картинку или временный документ?
Простая замена строки через функцию СтрЗаменить с указанием жесткого имени файла — решение ненадежное. При переименовании обработки пользователем такой код мгновенно перестанет работать. В этой статье мы подробно разберем три цивилизованных, надежных и профессиональных способа решения этой задачи: от стандартных возможностей платформы до высокопроизводительных методов БСП и строкового парсинга.
Самый простой и логичный способ, заложенный в саму платформу 1С:Предприятие — это использование специализированного объекта Файл. Этот объект инициализируется полным путем к файлу и позволяет обращаться к его свойствам напрямую, без необходимости вручную анализировать и резать строку.
У объекта Файл есть крайне полезное свойство Путь. Оно содержит полный путь к каталогу, в котором расположен файл, причем путь гарантированно завершается закрывающим слэшем (разделителем), что очень удобно для последующей конкатенации.
Рассмотрим пример реализации на практике:
// Получаем полный путь к текущей обработке
ПолныйПутьКФайлу = ПолучитьИспользуемоеИмяФайла();
// Инициализируем системный объект для работы с файлом
ОбъектФайл = Новый Файл(ПолныйПутьКФайлу);
// Извлекаем только путь к каталогу
КаталогОбработки = ОбъектФайл.Путь;
// Выводим результат пользователю
Сообщить(КаталогОбработки); // На выходе получим строку вида "C:\MyFolder\SubFolder\"
Этот способ лаконичен, легко читается и поддерживается. Однако у него есть важные архитектурные особенности, о которых мы поговорим в разделе сравнения методов.
Если вы ведете разработку в современной типовой конфигурации 1С (например, 1С:ERP, Управление торговлей, Бухгалтерия предприятия или Зарплата и управление персоналом), то в вашем распоряжении находится мощный инструмент — Библиотека стандартных подсистем (БСП). Разработчики фирмы «1С» уже написали оптимальный код для решения большинства повседневных задач.
Для разбора путей в БСП предусмотрена готовая кроссплатформенная функция общего назначения РазложитьПолноеИмяФайла. Она возвращает структуру со всеми необходимыми составляющими исходного пути.
Давайте разберем по шагам, как использовать этот метод в своем коде:
// Передаем полный путь к файлу в функцию БСП
ПолныйПуть = ПолучитьИспользуемоеИмяФайла();
СтруктураПути = ОбщегоНазначенияКлиентСервер.РазложитьПолноеИмяФайла(ПолныйПуть);
// Извлекаем необходимый нам каталог
КаталогОбработки = СтруктураПути.Путь;
// Дополнительно из структуры можно получить другие полезные данные:
// СтруктураПути.Имя — "обработка.epf"
// СтруктураПути.Расширение — ".epf"
// СтруктураПути.ИмяБезРасширения — "обработка"
Главный плюс данного метода — его абсолютная надежность и соответствие стандартам разработки фирмы «1С». Метод работает на стороне клиента и сервера, не обращаясь напрямую к операционной системе для инициализации файловых объектов.
Бывают ситуации, когда ваша обработка должна работать максимально быстро (например, при пакетной обработке сотен тысяч путей в цикле), либо код выполняется в жестких условиях безопасности (в веб-клиенте без расширения работы с файлами или в безопасном режиме в облаке «1С:Фреш»). В таких случаях прямое обращение к файловой системе через Новый Файл() может быть заблокировано или вызовет критическое падение производительности.
Для решения этой проблемы мы можем эффективно распарсить строку пути. Начиная с версии платформы 8.3.15, функция СтрНайти получила возможность поиска с конца строки, что позволяет нам за одну операцию отсечь имя файла.
Проанализируем универсальный код функции, которая корректно определит разделитель как для операционных систем семейства Windows (символ "\"), так и для Linux или Web-клиентов (символ "/"):
Функция ПолучитьКаталогИзПути(Знач ПолноеИмяФайла) Экспорт
// По умолчанию определяем разделитель для Linux/Web-среды
Разделитель = "/";
// Если в пути встречается обратный слэш, значит мы в Windows-среде
Если СтрНайти(ПолноеИмяФайла, "\") > 0 Тогда
Разделитель = "\";
КонецЕсли;
// Находим позицию самого последнего разделителя в строке (с конца)
ПозицияРазделителя = СтрНайти(ПолноеИмяФайла, Разделитель, НаправлениеПоиска.СКонца);
// Если разделитель найден, отсекаем всё, что находится правее него
Если ПозицияРазделителя > 0 Тогда
Возврат Лев(ПолноеИмяФайла, ПозицияРазделителя);
КонецЕсли;
// Если разделителей нет, значит передан некорректный путь
Возврат "";
КонецФункции
Этот метод работает мгновенно в оперативной памяти компьютера, не задействует ресурсы дисковой подсистемы и не требует никаких прав доступа от операционной системы.
Для того чтобы выбрать наиболее подходящий метод для вашей задачи, давайте сопоставим их ключевые характеристики:
Новый Файл() инициализирует полноценный системный объект операционной системы. Если выполнять эту операцию внутри цикла при чтении реестра файлов, производительность системы резко снизится. В высоконагруженных циклах используйте исключительно Способ 3 (строковый разбор) или Способ 2 (БСП).Файл напрямую в браузере (веб-клиент) невозможна без установленного «Расширения работы с файлами» и явного согласия пользователя. Если ваша обработка должна запускаться в браузере, использование Способа 1 приведет к ошибке выполнения. Строковые методы (Способы 2 и 3) работают в веб-клиенте без ограничений.Подведем итог: Для простых локальных обработок, запускаемых в толстом или тонком клиенте Windows, отлично подойдет лаконичный Способ 1. Для разработки внутри крупных современных конфигураций используйте готовый стандарт Способа 2. А для создания максимально производительных, кроссплатформенных и отказоустойчивых решений пишите строковый разбор по аналогии со Способом 3.