Разработка и Конфигурация · 9 мин
1С: как получить имя файла из полного имени файла
Как в 1С получить имя файла из полного пути: объект Файл, СтрНайти, разбор строки. Готовые функции, примеры кода, обработка ошибок и FAQ.
При разработке в 1С часто возникает задача: из строки вида «C:\Документы\Отчеты\Продажи.xlsx» получить только «Продажи.xlsx», а иногда — отдельно имя без расширения («Продажи») и само расширение («.xlsx»). Это нужно при загрузке файлов обмена, формировании имен вложений, проверке типов выгружаемых документов и записи файлов во временные каталоги.
Во встроенном языке 1С нет одной «волшебной» функции вида ПолучитьИмяФайла(), но задача решается несколькими штатными способами: через объект Файл, через поиск последнего разделителя в строке, а также через средства работы со строками. Каждый способ имеет свои ограничения, которые важно учитывать, чтобы код не падал на нестандартных путях.
Способ 1: объект Файл — самый простой и читаемый
Объект Файл предназначен для работы с файловой системой и умеет разбирать путь автоматически. Достаточно передать полное имя в конструктор и обратиться к нужным свойствам:
Файл = Новый Файл("C:\Документы\Отчеты\Продажи.xlsx");
ИмяФайла = Файл.Имя; // "Продажи.xlsx"
ИмяБезРасширения = Файл.ИмяБезРасширения; // "Продажи"
Расширение = Файл.Расширение; // ".xlsx"
ПутьКаталога = Файл.Путь; // "C:\Документы\Отчеты\"
Файл = Новый Файл(ПолноеИмяФайла);
ИмяФайла = Файл.Имя;
Расширение = НРег(Файл.Расширение);Этот способ хорош тем, что корректно решает сразу три задачи: извлекает имя, имя без расширения и расширение. Код получается коротким и понятным любому разработчику, который будет его сопровождать.
Важный нюанс: конструктор Новый Файл() не требует, чтобы файл реально существовал на диске. Объект создается как описание пути, поэтому свойства Имя и Расширение доступны даже для несуществующего файла. Однако обращение к другим свойствам (Размер(), ПолучитьВремяИзменения()) для несуществующего файла вызовет исключение.
Способ 2: разбор строки через СтрНайти
Если по каким-то причинам объект Файл использовать нежелательно (например, путь пришел с другой операционной системы, и разделитель неизвестен), можно разобрать строку вручную. Логика такая: найти последний разделитель каталога и взять всё, что правее него.
Функция ПолучитьИмяФайлаИзПути(ПолноеИмя) Экспорт
ПозицияСлэша = СтрНайти(ПолноеИмя, "\", НаправлениеПоиска.СКонца);
ПозицияДроби = СтрНайти(ПолноеИмя, "/", НаправлениеПоиска.СКонца);
Позиция = Макс(ПозицияСлэша, ПозицияДроби);
Если Позиция = 0 Тогда
Возврат ПолноеИмя; // разделителей нет — это уже имя файла
Иначе
Возврат Сред(ПолноеИмя, Позиция + 1);
КонецЕсли;
КонецФункции
Обратите внимание на проверку обоих разделителей — обратного слэша и прямого. Пути, приходящие из веб-сервисов, Linux-серверов или URL, используют «/», а локальные пути Windows — «\». Если проверять только один символ, часть путей будет разбираться неправильно.
Дополнительно стоит обработать ситуацию, когда путь заканчивается разделителем (например, «C:\Документы\»). В этом случае функция вернет пустую строку, и вызывающий код должен понимать, что передан каталог, а не файл.
Как отделить расширение от имени
После получения имени файла часто требуется разделить его на собственно имя и расширение. Если вы используете объект Файл, это уже сделано за вас. При ручном разборе логика похожа: ищем последнюю точку в имени файла.
Функция РазложитьИмяФайла(ИмяФайла, ИмяБезРасширения, Расширение) Экспорт
ПозицияТочки = СтрНайти(ИмяФайла, ".", НаправлениеПоиска.СКонца);
Если ПозицияТочки = 0 Тогда
ИмяБезРасширения = ИмяФайла;
Расширение = "";
Иначе
ИмяБезРасширения = Лев(ИмяФайла, ПозицияТочки - 1);
Расширение = Сред(ИмяФайла, ПозицияТочки); // включая точку
КонецЕсли;
КонецФункции
Для сравнения расширений всегда приводите их к одному регистру через НРег() или ВРег(): пользователи сохраняют файлы как «.XLSX», «.Xlsx» и «.xlsx», и сравнение без нормализации регистра даст ложное несовпадение.
Особенности тонкого клиента и веб-клиента
На клиенте работа с файловой системой ограничена. В тонком клиенте объект Файл доступен, но в веб-клиенте прямой доступ к диску пользователя через файловые функции невозможен без расширения работы с файлами. При этом разбор строки пути работает в любом контексте, поскольку это чисто строковые операции.
Типовой сценарий: пользователь выбирает файл через ДиалогВыбораФайла, и вы получаете полное имя. Если дальше файл передается на сервер через НачатьПомещениеФайла, то имя файла лучше извлечь на клиенте и передать отдельным параметром — на сервере исходный клиентский путь может быть недоступен или бессмыслен.
Типичные ошибки и как их избежать
Отдельная группа проблем — сетевые пути вида «\\server\share\file.txt». Оба описанных способа справляются с ними корректно, поскольку ищут последний разделитель, но при ручном разборе убедитесь, что вы не обрезаете двойной слэш в начале как обычный разделитель — для извлечения имени это не критично, а вот для получения каталога важно.
Проверка результата
После внедрения функции проверьте её на наборе граничных случаев, прежде чем использовать в прикладной логике.
Как проверить результат
Имя «a.xlsx», расширение «.xlsx»
Имя содержит часть пути или пустое
Имя «b.pdf»
Возвращается весь путь целиком
Имя «readme», расширение пустое
Ошибка или расширение равно всему имени
Пустое имя, обработанное в коде
Необработанное исключение в вызывающем коде
Расширение «.xlsx», имя «отчет.v2»
Расширение «.v2.xlsx»
Какой способ выбрать
Сравнение вариантов
Подходит почти всегда: короткий код, сразу дает Имя, ИмяБезРасширения и Расширение. Ограничение — привязка к разделителям текущей ОС сервера/клиента.
Подходит для путей из чужих систем (веб-сервисы, Linux, URL), где разделитель неизвестен. Требует аккуратной обработки граничных случаев.
Быстрый вариант: взять последний элемент массива. Минус — создается массив всех частей пути, что избыточно для длинных путей.
В большинстве прикладных решений достаточно объекта Файл. Ручной разбор строки оправдан в обменах с внешними системами, где формат пути не контролируется вашей конфигурацией. Комбинировать оба подхода в одной универсальной функции общего модуля — хорошая практика: такая функция пишется один раз и переиспользуется во всех механизмах загрузки и выгрузки.
Что важно запомнить
Проще всего извлечь имя файла через объект Файл и его свойства Имя, ИмяБезРасширения, Расширение — это работает даже для несуществующего файла. Для путей из внешних систем используйте СтрНайти с поиском с конца по обоим разделителям. Всегда нормализуйте регистр расширения и обрабатывайте пустой результат.
Часто задаваемые вопросы
Работает ли «Новый Файл», если файла нет на диске?
Да. Конструктор создает объект-описание пути, и свойства Имя, ИмяБезРасширения, Расширение и Путь доступны независимо от существования файла. Исключение возникнет только при обращении к свойствам, требующим реального файла: размеру, времени изменения и подобным.
Как получить имя файла из пути, который пришел с Linux-сервера?
Объект Файл на Windows-сервере может некорректно разобрать путь с прямыми слэшами. Надежнее использовать ручной разбор: найти через СтрНайти с направлением СКонца последний символ «/» и взять подстроку правее него функцией Сред.
Чем отличаются свойства Имя и ИмяБезРасширения?
Имя возвращает файл целиком вместе с расширением («Продажи.xlsx»), а ИмяБезРасширения — только основную часть («Продажи»). Для формирования нового файла с тем же именем, но другим расширением удобнее второе свойство.
Можно ли получить имя файла на сервере, если файл выбрал пользователь на клиенте?
Можно, если передать полное имя строкой в серверную процедуру и разобрать его как строку. Но читать содержимое файла по этому пути на сервере нельзя — сначала поместите файл во временное хранилище на клиенте.
Как проверить, что у файла допустимое расширение?
Извлеките расширение, приведите его к нижнему регистру через НРег и сравните со списком разрешенных значений, например через соответствие или массив с методом Найти. Без приведения регистра файлы «.XLSX» и «.xlsx» будут считаться разными типами.
Что вернет разбор, если в пути нет разделителей?
Это означает, что передана уже чистая имя файла без каталога. Корректная функция должна вернуть исходную строку без изменений — именно поэтому в примере с СтрНайти есть проверка результата на ноль.