Пути к файлам и каталогам во встроенном языке 1С:Предприятия 8.3
Содержание
Путь к файлу в 1С указывают обычной строкой: "C:\Обмен\price.xlsx" в Windows, "/var/obmen/price.xlsx" в Linux или "\\srv-files\obmen\price.xlsx" для сетевой папки. Экранировать обратную косую черту не нужно: во встроенном языке 1С \ внутри строки — обычный символ, удваивают только кавычки.
Частая ошибка — проверить путь на своём компьютере и удивляться, что на сервере «файл не найден». Путь всегда относится к той машине, где выполняется код. Процедура с директивой &НаСервере ищет файл на диске сервера 1С, а не у бухгалтера на рабочем столе. Отсюда половина вопросов про каталоги, сетевые диски и права.
Как записать путь к файлу в 1С: абсолютный, относительный, разделитель
Платформа принимает путь как строку и передаёт её операционной системе почти без изменений. Поэтому правила записи — это правила той ОС, где работает код.
📌 Варианты записи:
- Абсолютный путь Windows — с буквой диска:
C:\Обмен\Входящие\price.xlsx. - Абсолютный путь Linux — от корня:
/home/usr1cv8/obmen/price.xlsx. - Сетевой путь (UNC) — с именем сервера:
\\srv-files\obmen\price.xlsx. - Относительный путь —
obmen\price.xlsx. Считается от текущего каталога процесса, а это обычно каталогbinплатформы. Для рабочего кода такой путь непредсказуем — лучше не использовать.
Кириллица и пробелы в путях допустимы. Строку в кавычках платформа передаёт целиком, дополнительно брать путь «в кавычки внутри кавычек» не нужно. Исключение — когда путь уходит параметром в командную строку через ЗапуститьПриложение(): там внутренние кавычки нужны, и их удваивают: """C:\Program Files\app.exe""".
Как собрать путь из частей
Склеивать каталог и имя файла «на глаз» опасно: в одном месте каталог заканчивается разделителем, в другом нет. В итоге получается C:\ОбменPrice.xlsx или C:\Обмен\\price.xlsx. Разделитель текущей ОС возвращает функция ПолучитьРазделительПути().
Функция СоединитьПуть(Каталог, ИмяФайла)
Разделитель = ПолучитьРазделительПути();
Если СтрЗаканчиваетсяНа(Каталог, Разделитель) Тогда
Возврат Каталог + ИмяФайла;
КонецЕсли;
Возврат Каталог + Разделитель + ИмяФайла;
КонецФункции
Если код выполняется на клиенте, а путь собирается для сервера (или наоборот), используйте ПолучитьРазделительПутиСервера() и ПолучитьРазделительПутиКлиента(). Это актуально, когда пользователи сидят под Windows, а сервер 1С стоит на Linux.
Не храните в константах и справочниках полный путь вместе с именем файла. Храните каталог отдельно, а имя собирайте в коде. Переезд обмена на другой диск тогда сводится к правке одной строки.
Где выполняется код и чей это путь
Это главный вопрос, без которого остальное не работает . В управляемых формах код разделён директивами.
| Где выполняется | Директива | К чьему диску относится путь |
|---|---|---|
| Клиент | &НаКлиенте | Компьютер пользователя (в веб-клиенте — с ограничениями) |
| Сервер 1С | &НаСервере, &НаСервереБезКонтекста, общие модули «Сервер» | Диск машины с рабочим процессом rphost |
| Файловая база, тонкий клиент | любые серверные процедуры | Компьютер пользователя: «сервер» выполняется в его процессе |
| Регламентное задание | серверный код | Диск сервера, права учётной записи службы |
В файловом варианте всё выглядит одинаково, и разработчик не замечает разницы. Проблемы всплывают после перевода базы на клиент-серверный вариант: тот же код начинает искать C:\Обмен уже на сервере.
Как передать файл пользователя на сервер
Если файл лежит у пользователя, а обработать его нужно на сервере, путь передавать бессмысленно — серверу этот диск не виден. Передают содержимое:
- На клиенте пользователь выбирает файл диалогом.
- Файл помещается во временное хранилище (
НачатьПомещениеФайлаНаСерверилиПоместитьФайлНаСерверАсинхв зависимости от версии платформы). - На сервер уходит адрес хранилища, там
ПолучитьИзВременногоХранилища()возвращаетДвоичныеДанные. - Двоичные данные записывают во временный файл на сервере и работают уже с ним.
Выбор файла пользователем на клиенте:
&НаКлиенте
Процедура ВыбратьФайл(Команда)
Диалог = Новый ДиалогВыбораФайла(РежимДиалогаВыбораФайла.Открытие);
Диалог.Фильтр = "Книга Excel (*.xlsx)|*.xlsx";
Диалог.МножественныйВыбор = Ложь;
Диалог.Показать(Новый ОписаниеОповещения("ВыборФайлаЗавершение", ЭтотОбъект));
КонецПроцедуры
&НаКлиенте
Процедура ВыборФайлаЗавершение(ВыбранныеФайлы, ДополнительныеПараметры) Экспорт
Если ВыбранныеФайлы <> Неопределено Тогда
ПутьКФайлу = ВыбранныеФайлы[0]; // реквизит формы
КонецЕсли;
КонецПроцедуры
Для выбора папки тот же объект создают с режимом РежимДиалогаВыбораФайла.ВыборКаталога, а результат берут из свойства Каталог или из первого элемента массива.
Объект Файл: проверить путь и разобрать его на части
Объект Файл не открывает файл и не блокирует его. Это «описание пути»: он разбирает строку на части и умеет спросить у ОС, существует ли такой объект.
ФайлНаДиске = Новый Файл("C:\Обмен\Входящие\price.xlsx");
ФайлНаДиске.ПолноеИмя; // C:\Обмен\Входящие\price.xlsx
ФайлНаДиске.Путь; // C:\Обмен\Входящие\ (с разделителем на конце)
ФайлНаДиске.Имя; // price.xlsx
ФайлНаДиске.ИмяБезРасширения; // price
ФайлНаДиске.Расширение; // .xlsx (с точкой)
Если ФайлНаДиске.Существует() И ФайлНаДиске.ЭтоФайл() Тогда
РазмерБайт = ФайлНаДиске.Размер();
Изменен = ФайлНаДиске.ПолучитьВремяИзменения();
КонецЕсли;
✅ Что полезно помнить:
- Свойство
Путьвозвращает каталог с завершающим разделителем — к нему можно сразу дописывать имя. Расширениесодержит точку. Сравнивайте с".xlsx", а не с"xlsx", и приводите к нижнему регистру черезНРег().ЭтоКаталог()отличает папку от файла с тем же именем. ПередСоздатьКаталог()проверяйте именно его.- На клиенте синхронные методы
Существует()иРазмер()в новых конфигурациях заменяют асинхронными (СуществуетАсинх()и аналоги). В серверном коде синхронные вызовы остаются нормой.
Глобальные функции для работы с каталогами
| Функция | Что делает |
|---|---|
НайтиФайлы(Каталог, Маска, ИскатьВПодкаталогах) | Возвращает массив объектов Файл по маске, например "*.xml" |
СоздатьКаталог(Путь) | Создаёт каталог, в том числе вложенный |
КопироватьФайл(Источник, Приемник) | Копирует, существующий приёмник перезаписывает |
ПереместитьФайл(Источник, Приемник) | Переносит или переименовывает |
УдалитьФайлы(Каталог, Маска) | Удаляет файлы по маске; без маски — сам путь |
Вызов УдалитьФайлы() с пустой или неверно собранной переменной каталога может удалить не то, что задумано. Перед удалением проверяйте, что путь непустой и начинается с ожидаемого корня, например с каталога временных файлов.
ФайловыйПоток и другие способы открыть файл по пути
Когда путь собран и проверен, файл открывают одним из объектов. Выбор зависит от задачи.
| Задача | Объект | Пример открытия по пути |
|---|---|---|
| Прочитать текст целиком или построчно | ЧтениеТекста, ТекстовыйДокумент | Новый ЧтениеТекста(Путь, КодировкаТекста.UTF8) |
| Записать текстовый файл | ЗаписьТекста, ТекстовыйДокумент | Новый ЗаписьТекста(Путь, КодировкаТекста.UTF8) |
| Взять файл как двоичные данные | ДвоичныеДанные | Новый ДвоичныеДанные(Путь) |
| Читать частями, большой файл | ФайловыйПоток, ЧтениеДанных | ФайловыеПотоки.ОткрытьДляЧтения(Путь) |
| XML, JSON | ЧтениеXML, ЧтениеJSON | метод ОткрытьФайл(Путь) |
ФайловыйПоток появился в платформе 8.3.9 вместе с менеджером ФайловыеПотоки. Он нужен, когда файл слишком велик, чтобы держать его в памяти, или когда читать надо с определённой позиции.
Поток = ФайловыеПотоки.ОткрытьДляЧтения(ПолноеИмя);
Попытка
Размер = Поток.Размер();
Буфер = Новый БуферДвоичныхДанных(Размер);
Поток.Прочитать(Буфер, 0, Размер);
Исключение
Поток.Закрыть();
ВызватьИсключение;
КонецПопытки;
Поток.Закрыть();
Полная форма конструктора задаёт режим и доступ явно:
Поток = Новый ФайловыйПоток(ПолноеИмя, РежимОткрытияФайла.Открыть, ДоступКФайлу.Чтение);
Для записи берут ФайловыеПотоки.Создать(Путь) или ОткрытьДляЗаписи(Путь). Поток обязательно закрывают методом Закрыть(). Незакрытый поток держит файл: другая программа или повторный запуск обработки получат ошибку доступа.
Кодировку указывайте явно. Без параметра ЧтениеТекста пытается определить её сам, и выгрузка из сторонней системы в Windows-1251 читается «кракозябрами». Для такого файла пишите КодировкаТекста.ANSI или строку "windows-1251".
Системные каталоги и временные файлы
Жёстко прописанный C:\Temp сломается на первом же сервере, где такой папки нет или у службы нет туда прав. Платформа сама подскажет нужные каталоги.
🗂 Функции, которые возвращают путь:
КаталогВременныхФайлов()— временный каталог текущего пользователя ОС. На сервере это временная папка учётной записи службы 1С.ПолучитьИмяВременногоФайла("xml")— уникальное имя во временном каталоге с нужным расширением. Сам файл не создаётся, только имя.КаталогПрограммы()— каталог исполняемых файлов платформы, например...\1cv8\8.3.25.xxxx\bin\. Писать туда не стоит.КаталогДокументов()— папка «Документы» пользователя. Имеет смысл только на клиенте.КаталогРабочихДанныхПользователя()— рабочий каталог пользователя 1С на клиенте.
Типовой шаблон обработки на сервере: получить временное имя, записать данные, обработать, удалить.
ИмяВременногоФайла = ПолучитьИмяВременногоФайла("xlsx");
ДвоичныеДанные = ПолучитьИзВременногоХранилища(АдресФайла);
ДвоичныеДанные.Записать(ИмяВременногоФайла);
Попытка
ОбработатьФайл(ИмяВременногоФайла);
Исключение
УдалитьФайлы(ИмяВременногоФайла);
ВызватьИсключение;
КонецПопытки;
УдалитьФайлы(ИмяВременногоФайла);
Временные файлы платформа сама не чистит. Если код падает до удаления, каталог Temp учётной записи службы за месяцы разрастается до гигабайт. Удаление в ветке Исключение решает проблему.
💡 В конфигурациях на БСП есть общий модуль ФайловаяСистема с функциями для временных файлов и каталогов. Если пишете доработку типовой, пользуйтесь им — так ваш код будет вести себя как остальная конфигурация.
Сетевые пути и UNC-адреса в 1С
Сетевую папку указывают в формате UNC: два обратных слэша, имя сервера (или IP), имя общего ресурса, дальше путь.
КаталогОбмена = "\\srv-files\obmen\1c\";
КаталогОбменаПоIP = "\\192.168.10.15\obmen\1c\";
Тут почти всегда ломается одно и то же — сетевой диск. Пользователь видит Z:\obmen, разработчик пишет этот путь в настройке, а на сервере 1С путь не работает.
🔌 Почему так происходит:
- Подключённые буквы дисков существуют только в сеансе пользователя, который их подключил. Служба агента сервера 1С работает в своём сеансе и диска
Z:не видит. - Служба запущена от отдельной учётной записи (по умолчанию
USR1CV8). Права на общую папку нужны именно ей, а не бухгалтеру. - Если учётная запись службы локальная, а не доменная, доступ к ресурсам другого компьютера по сети обычно не проходит.
Порядок настройки:
- Узнайте, под какой учётной записью запущена служба «Агент сервера 1С:Предприятия» (оснастка «Службы» Windows, вкладка «Вход в систему»).
- Дайте этой учётной записи права на чтение и запись в общую папку: и на вкладке «Доступ», и на вкладке «Безопасность».
- Укажите в настройке обмена UNC-путь, а не букву диска.
- Проверьте доступ под этой учётной записью: откройте путь в Проводнике от её имени.
Смена учётной записи службы вступает в силу после её перезапуска. Перезапуск агента обрывает все сеансы пользователей на сервере — делайте это вне рабочего времени и с предупреждением.
Windows и Linux: кроссплатформенные пути
Когда сервер 1С стоит на Linux, код, написанный под Windows, ломается в предсказуемых местах.
| Что | Windows | Linux |
|---|---|---|
| Разделитель | \ | / |
| Корень | буква диска C:\ | / |
| Регистр имён | не важен: Price.XLSX = price.xlsx | важен: это два разных файла |
| Сетевая папка | \\server\share напрямую | только смонтированная, например /mnt/obmen |
| Учётная запись службы | USR1CV8 (по умолчанию) | usr1cv8 |
| Временный каталог | C:\Users\<учётка>\AppData\Local\Temp\ | обычно /tmp/ |
UNC-путь сервер на Linux не понимает. Общую папку Windows монтируют в файловую систему средствами ОС и в настройках 1С указывают точку монтирования:
sudo mount -t cifs //srv-files/obmen /mnt/obmen -o username=obmen1c,uid=usr1cv8,gid=grp1cv8
Для постоянного подключения ту же строку прописывают в /etc/fstab, а пароль выносят в отдельный файл с правами только для root.
🐧 Чтобы один код работал на обеих ОС:
- собирайте пути через
ПолучитьРазделительПути(), а не строковыми константами со слэшами; - имена файлов сравнивайте после
НРег(), а маски вНайтиФайлы()пишите с учётом регистра ("*.xml"не найдётORDER.XMLна Linux); - не используйте букву диска и
КаталогДокументов()в серверном коде; - храните каталог обмена в настройке, чтобы для Linux-сервера его можно было указать отдельно.
Ошибки при работе с путями и как их обработать
Любая операция с файлом может упасть: файл заняли, сеть пропала, прав нет. Без обработки пользователь видит системное окно, а регламентное задание молча останавливается. Файловые операции оборачивают в Попытка…Исключение и пишут причину в журнал регистрации.
Попытка
КопироватьФайл(Источник, Приемник);
Исключение
Инфо = ИнформацияОбОшибке();
ЗаписьЖурналаРегистрации("Обмен.КопированиеФайла",
УровеньЖурналаРегистрации.Ошибка, , ,
ПодробноеПредставлениеОшибки(Инфо));
ВызватьИсключение СтрШаблон("Не удалось скопировать %1 в %2: %3",
Источник, Приемник, КраткоеПредставлениеОшибки(Инфо));
КонецПопытки;
Журнал регистрации смотрят в Администрирование → Обслуживание → Журнал регистрации (БП 3.0, ЗУП 3.1, УТ 11), отбор по событию Обмен.КопированиеФайла.
Ещё одна причина отказа — безопасный режим. Внешние обработки и расширения, подключённые в безопасном режиме, не получают доступа к файловой системе. Тогда код с путями падает, хотя путь верный. Решение — подключать обработку без безопасного режима или настроить профиль безопасности с разрешением на нужный каталог.
Частые вопросы
Нужно ли удваивать обратную косую черту в пути в 1С?
\ не служит экранирующим символом. Пишите "C:\Обмен\file.xml" как есть. Удваивают только двойные кавычки внутри строки.Можно ли указать путь с кириллицей и пробелами?
Как получить путь к каталогу, где лежит база?
СтрокаСоединенияИнформационнойБазы() вернёт её в виде File="C:\Base\Buh";, каталог выделяют разбором строки. Для клиент-серверной базы каталога на диске нет: там указаны сервер и имя базы.