Пустой файл из кода 1С:Предприятия 8.3 — от нуля байт до шаблона
Содержание
Быстрее всего пустой файл в 1С создаётся двумя строками: Запись = Новый ЗаписьДанных(ИмяФайла); Запись.Закрыть();. На диске появится файл размером 0 байт. Те же 0 байт дают пустые ДвоичныеДанные, записанные методом Записать(), и ФайловыйПоток в режиме РежимОткрытияФайла.Создать.
Подвохов три. Код на сервере создаёт файл на диске сервера, а не у пользователя. Текстовые объекты в UTF-8 добавляют BOM, и файл уже не пустой. А «пустой» XLSX или DOCX нулевой длины Excel и Word не откроют. Ниже всё это разобрано по порядку, с готовым кодом для платформы 8.3.
Что считать пустым файлом и где он появится
Перед тем как писать код, ответьте себе на два вопроса.
Что значит «пустой» в вашей задаче:
- 📄 0 байт — маркер, флаг-файл для обмена, «заглушка» для внешней системы, которая проверяет только факт наличия файла;
- 🔤 пустой текст в нужной кодировке — файл, куда потом будут дописывать строки, и кодировка должна быть определена с первого байта;
- 📊 пустой документ формата — XLSX, DOCX, PDF, ZIP. Это контейнеры со служебной структурой, у них не бывает нуля байт.
Где выполняется код:
| Контекст | Где окажется файл | Что учесть |
|---|---|---|
Серверная процедура (&НаСервере, общий модуль на сервере, фоновое задание) | На машине сервера 1С | Права учётной записи службы сервера |
| Файловая база, толстый или тонкий клиент | На компьютере пользователя | Права пользователя Windows |
| Клиентская процедура в тонком клиенте | На компьютере пользователя | Синхронные вызовы могут быть запрещены конфигурацией |
| Веб-клиент | Прямой записи на диск нет | Только передача файла через браузер |
В клиент-серверной базе путь вида C:\Обмен\flag.txt в серверном коде означает диск сервера. Если файл нужен пользователю, создайте данные на сервере, положите их во временное хранилище и отдайте на клиент.
Пустые двоичные данные: самый короткий путь
Объект ДвоичныеДанные нельзя создать пустым через Новый ДвоичныеДанные() — конструктор ждёт имя существующего файла. Пустой экземпляр получают обходными путями, их три.
Вариант 1. Из пустой строки
ПустыеДанные = ПолучитьДвоичныеДанныеИзСтроки("");
ПустыеДанные.Записать(ИмяФайла);
Пустая строка превращается в двоичные данные длиной 0. Проверить можно так: ПустыеДанные.Размер() вернёт 0.
Вариант 2. Через поток в памяти
Поток = Новый ПотокВПамяти;
ПустыеДанные = Поток.ЗакрытьИПолучитьДвоичныеДанные();
ПустыеДанные.Записать(ИмяФайла);
Этот вариант удобен, если код дальше может что-то записать в поток по условию. Не записали ничего — получили пустой файл без отдельной ветки.
Вариант 3. ЗаписьДанных без записи
Запись = Новый ЗаписьДанных(ИмяФайла);
Запись.Закрыть();
Конструктор ЗаписьДанных открывает файл на запись и создаёт его. Метод Закрыть() освобождает файл. Если файл уже был, его содержимое будет заменено пустым.
Не забывайте Закрыть(). Пока объект записи жив, файл занят процессом 1С. Удалить или переименовать его не получится ни из кода, ни из проводника.
Когда нужны именно двоичные данные
Пустые ДвоичныеДанные полезны не только для диска:
- 📎 вложение в письмо —
Сообщение.Вложения.Добавить(ПустыеДанные, "empty.txt")у объектаИнтернетПочтовоеСообщение; - 🗄 реквизит типа ХранилищеЗначения —
Новый ХранилищеЗначения(ПустыеДанные); - 📤 передача на клиент —
ПоместитьВоВременноеХранилище(ПустыеДанные, УникальныйИдентификатор).
Файловые потоки: контроль над созданием
С версии 8.3.9 в платформе есть потоки. Для пустого файла они дают то, чего нет у других способов: явный выбор, что делать, если файл уже существует.
Поток = Новый ФайловыйПоток(ИмяФайла, РежимОткрытияФайла.СоздатьНовый);
Поток.Закрыть();
Режимы, которые пригодятся:
| Режим | Файла нет | Файл есть |
|---|---|---|
Создать | Создаёт пустой | Перезаписывает до 0 байт |
СоздатьНовый | Создаёт пустой | Вызывает исключение |
ОткрытьИлиСоздать | Создаёт пустой | Открывает, содержимое не трогает |
СоздатьНовый — хороший способ сделать простую блокировку между двумя заданиями. Первое создаёт флаг-файл, второе получает исключение и понимает, что работа уже идёт. Оборачивайте вызов в Попытка … Исключение.
ОткрытьИлиСоздать нужен, когда файл-журнал должен существовать, но затирать накопленное нельзя.
Режим Создать молча обнуляет существующий файл. Если по ошибке передать путь к рабочему файлу, данные пропадут без предупреждения.
Пример: флаг-файл для обмена с внешней системой
Частая схема интеграции: 1С выгружает данные в каталог обмена, а внешняя программа забирает их только после появления пустого файла-маркера, например ready.flag. Так получатель не начнёт читать выгрузку, которая ещё пишется.
Порядок действий в регламентном задании:
- Удалите старый маркер, если он остался с прошлого запуска.
- Запишите файл выгрузки полностью и закройте его.
- Создайте пустой
ready.flagлюбым двоичным способом.
Маркер создаётся последним — в этом весь смысл. Если задание упадёт посередине выгрузки, маркера не будет, и внешняя система не возьмёт неполные данные. Получатель после обработки удаляет маркер сам, и цикл повторяется.
Имя маркера и каталог согласуйте с разработчиками второй стороны письменно. Расхождение в одной букве или в регистре (на Linux Ready.flag и ready.flag — разные файлы) приводит к тому, что обмен «молча» стоит.
Временные файлы: имя, каталог и уборка
Пустой файл часто нужен как промежуточный: создать, заполнить, отправить, удалить. Для этого в платформе есть функция ПолучитьИмяВременногоФайла().
ИмяФайла = ПолучитьИмяВременногоФайла("txt");
Запись = Новый ЗаписьДанных(ИмяФайла);
Запись.Закрыть();
// ... работа с файлом ...
УдалитьФайлы(ИмяФайла);
Что важно знать про эту функцию:
- Она возвращает только имя в каталоге временных файлов. Сам файл не создаётся — его создаёт ваш код.
- Параметр — расширение без точки:
"txt","xml","xlsx". - Каталог временных файлов возвращает
КаталогВременныхФайлов(). На сервере это временный каталог учётной записи, под которой работает служба 1С. - Платформа не удаляет такие файлы за вас. Уборка — задача кода.
Временные файлы в типовых конфигурациях
В конфигурациях на БСП (Бухгалтерия 3.0, ЗУП 3.1, УТ 11 и другие) для этого есть общий модуль ФайловаяСистема. Функция ФайловаяСистема.СоздатьВременныйФайл("txt") возвращает имя во временном каталоге, а ФайловаяСистема.УдалитьВременныйФайл(ИмяФайла) его удаляет. В новых редакциях БСП прямой вызов ПолучитьИмяВременногоФайла() проверка конфигурации помечает как нежелательный, поэтому в доработках типовых лучше пользоваться модулем библиотеки.
Уборку ставьте так, чтобы она выполнилась даже при ошибке:
ИмяФайла = ПолучитьИмяВременногоФайла("txt");
Попытка
Запись = Новый ЗаписьДанных(ИмяФайла);
Запись.Закрыть();
ОтправитьФайл(ИмяФайла); // ваша процедура
Исключение
УдалитьФайлы(ИмяФайла);
ВызватьИсключение;
КонецПопытки;
УдалитьФайлы(ИмяФайла);
Пустой текстовый файл и ловушка BOM
Если файл текстовый и в него потом будут писать строки, удобнее объекты ЗаписьТекста и ТекстовыйДокумент. Но у них есть особенность, о которой многие узнают только по жалобе от внешней системы.
ЗаписьТекста
Запись = Новый ЗаписьТекста(ИмяФайла, КодировкаТекста.ANSI);
Запись.Закрыть();
В кодировке ANSI файл получится нулевого размера. С КодировкаТекста.UTF8 в начале файла окажется метка порядка байтов (BOM) — три байта EF BB BF. Для Блокнота файл пустой, для программы, которая сверяет размер с нулём, — нет.
ТекстовыйДокумент
Текст = Новый ТекстовыйДокумент;
Текст.Записать(ИмяФайла, КодировкаТекста.UTF8);
Поведение то же: UTF-8 с меткой. Плюс ТекстовыйДокумент держит весь текст в памяти, поэтому для больших файлов, которые будут дописываться построчно, он хуже ЗаписьТекста.
Как получить UTF-8 без BOM
Надёжный путь — работать через двоичные данные и явно отключить метку третьим параметром:
Данные = ПолучитьДвоичныеДанныеИзСтроки(СтрокаДанных, КодировкаТекста.UTF8, Ложь);
Данные.Записать(ИмяФайла);
Пока строка пустая, файл будет 0 байт. Когда появится содержимое, оно запишется в UTF-8 без метки.
Нужен пустой файл ровно 0 байт — не используйте текстовые объекты в UTF-8. Возьмите любой двоичный способ из разделов выше.
Пустые документы офисных форматов
Файл report.xlsx размером 0 байт Excel не откроет: формат — это ZIP-архив со служебными XML внутри. Правильный пустой XLSX создаётся из пустого табличного документа:
Таблица = Новый ТабличныйДокумент;
Таблица.Записать(ИмяФайла, ТипФайлаТабличногоДокумента.XLSX);
Так же получаются пустые MXL, PDF, ODS, HTML — меняется только значение ТипФайлаТабличногоДокумента. Для пустого DOCX подходит ФорматированныйДокумент или пустой макет-шаблон, записанный в файл.
Сравнение способов создать пустой файл
| Способ | Размер результата | Версия платформы | Когда брать |
|---|---|---|---|
ЗаписьДанных + Закрыть() | 0 байт | 8.3.9 и выше | Флаг-файл, заглушка |
ПолучитьДвоичныеДанныеИзСтроки("") + Записать() | 0 байт | 8.3 | Когда данные нужны ещё и в памяти (вложение, хранилище) |
ПотокВПамяти | 0 байт | 8.3.9 и выше | Содержимое пишется по условию |
ФайловыйПоток, режим СоздатьНовый | 0 байт | 8.3.9 и выше | Нельзя затереть существующий файл, блокировка заданий |
ЗаписьТекста, ANSI | 0 байт | Любая 8.x | Текст в Windows-1251 для старых систем |
ЗаписьТекста или ТекстовыйДокумент, UTF-8 | 3 байта (BOM) | Любая 8.x | Текстовый файл, где метка нужна или не мешает |
ТабличныйДокумент.Записать() | Несколько КБ | 8.3 | Пустой XLSX, PDF, MXL |
Вызывать для этой задачи ЗапуститьПриложение() с командами Windows не стоит. Такой код не работает
на сервере под Linux, зависит от настроек безопасности и не возвращает понятной ошибки.
Новый пустой внешний отчёт или обработка
Иногда под «пустым файлом» понимают заготовку внешнего отчёта .erf или обработки .epf. Из встроенного языка такой файл не создать — его делают в конфигураторе:
- Запустите базу в режиме «Конфигуратор». Открывать конфигурацию не обязательно.
- Выберите
Файл → Новый…. - В списке укажите «Внешний отчет » или «Внешняя обработка».
- Задайте имя объекта латиницей или кириллицей без пробелов. Это имя увидит пользователь в форме.
- Сохраните:
Файл → Сохранить как…и укажите путь к.erfили.epf.
Получится пустая оболочка без реквизитов, форм и макетов. Для отчёта на СКД сразу откройте его свойства и создайте основную схему компоновки данных, иначе отчёт не будет формироваться.
Подключение в типовой конфигурации
Чтобы такой отчёт был доступен всем пользователям в программах на БСП, его регистрируют в справочнике дополнительных отчётов и обработок: НСИ и администрирование → Печатные формы, отчеты и обработки → Дополнительные отчеты и обработки в Бухгалтерии 3.0. Для этого в модуле объекта нужна функция СведенияОВнешнейОбработке(). Пустой отчёт без неё можно открыть только через Файл → Открыть.
Для сборки из исходников без интерфейса подходит пакетный режим конфигуратора с параметром /LoadExternalDataProcessorOrReportFromFiles. Он собирает .epf или .erf из XML-выгрузки, что удобно в Git-процессах.
Ошибки при создании файла и права доступа
Код создания файла из одной строки может упасть по нескольким причинам. Почти все они связаны не с 1С, а с правами и путями.
Как ловить ошибку правильно
Попытка
Запись = Новый ЗаписьДанных(ИмяФайла);
Запись.Закрыть();
Исключение
Информация = ИнформацияОбОшибке();
ЗаписьЖурналаРегистрации("Создание файла", УровеньЖурналаРегистрации.Ошибка, , ИмяФайла,
ПодробноеПредставлениеОшибки(Информация));
ВызватьИсключение КраткоеПредставлениеОшибки(Информация);
КонецПопытки;
Подробности уходят в журнал регистрации для администратора, пользователь видит короткое сообщение. Функции КраткоеПредставлениеОшибки() и ПодробноеПредставлениеОшибки() доступны с 8.3.17. На более старых версиях используйте ОписаниеОшибки().
Проверка результата
После создания убедитесь, что файл есть и его размер тот, что нужен:
Файл = Новый Файл(ИмяФайла);
Если Не Файл.Существует() Или Файл.Размер() <> 0 Тогда
ВызватьИсключение "Не удалось создать пустой файл " + ИмяФайла;
КонецЕсли;
Передача пустого файла пользователю
Если файл создан на сервере, а сохранить его надо у пользователя:
- На сервере получите двоичные данные и вызовите
ПоместитьВоВременноеХранилище(Данные, УникальныйИдентификатор). - Верните адрес на клиент.
- В конфигурации на БСП вызовите
ФайловаяСистемаКлиент.СохранитьФайл(Оповещение, Адрес, "empty.txt"). Метод сам выберет подходящий для клиента способ, включая веб-клиент.