Как создать новый текстовый файл при каждом запуске обработки в 1С, не перезаписывая старый?

Программист IT и автоматизация бизнеса
← На главную

Часто возникает задача, когда регламентное задание или внешняя обработка должны сохранять результаты своей работы в текстовый файл. Стандартная проблема при этом — каждый новый запуск перезаписывает файл, созданный в предыдущий раз, и мы теряем историю. Давайте разберем, как решить эту проблему и настроить создание уникального файла при каждом запуске.

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

Решение 1: Использование текущей даты и времени в имени файла

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

Посмотрим на пример кода, который решает эту задачу. Нам понадобится функция Формат(), которая преобразует текущую дату в строку нужного нам вида.


// Определяем каталог, куда будем сохранять файлы
Каталог = "C:\Temp\Logs";

// Формируем уникальное имя файла, добавляя дату и время
// ДФ (DF) - это параметр формата даты (DateFormat)
ИмяФайла = Каталог + "\Файл_" + Формат(ТекущаяДата(), "ДФ=дд.ММ.гггг_ЧЧ_мм_сс") + ".txt";

// Создаем и записываем текстовый документ
ТекстовыйФайл = Новый ТекстовыйДокумент;
ТекстовыйФайл.ДобавитьСтроку("Это тестовая строка для файла.");
ТекстовыйФайл.Записать(ИмяФайла);

В этом примере "ДФ=дд.ММ.гггг_ЧЧ_мм_сс" означает:

Таким образом, мы получим файлы с именами вида Файл_21.10.2023_15_30_05.txt, что гарантирует их уникальность при запусках с интервалом более секунды.

Решение 2: Альтернативные и более надежные способы генерации имени

Хотя метод с датой и временем хорош, в высоконагруженных системах или при очень частых запусках могут возникать коллизии (совпадения имен). Рассмотрим более надежные методы, которые гарантируют уникальность практически на 100%.

1. Использование универсальной даты в миллисекундах

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


// Получаем количество миллисекунд в виде строки
СтрокаМиллисекунд = Формат(ТекущаяУниверсальнаяДатаВМиллисекундах(), "ЧГ="); // ЧГ= убирает разделители групп

ИмяФайла = Каталог + "\Файл_" + СтрокаМиллисекунд + ".txt";

В результате имя файла будет выглядеть примерно так: Файл_63833489405123.txt.

2. Использование уникального идентификатора (GUID)

Это самый надежный способ. Уникальный идентификатор (GUID) — это 128-битное число, которое генерируется по алгоритму, гарантирующему его уникальность во всем мире. В 1С для этого есть объект УникальныйИдентификатор.


// Генерируем новый GUID
НовыйGUID = Новый УникальныйИдентификатор;

// Преобразуем его в строку и используем в имени файла
ИмяФайла = Каталог + "\Файл_" + Формат(НовыйGUID) + ".txt";

Имя файла будет выглядеть так: Файл_b2a7a4b0-51a8-11ee-8a3c-00155d012101.txt. Этот метод является промышленным стандартом для создания уникальных имен.

3. Использование генератора случайных чисел

Еще один вариант — добавить к имени файла случайное число. Этот метод не дает 100% гарантии уникальности, но вероятность совпадения очень низка. Для этого используется объект ГенераторСлучайныхЧисел.


ГСЧ = Новый ГенераторСлучайныхЧисел;

// Генерируем случайное число в большом диапазоне
СлучайноеЧисло = ГСЧ.СлучайноеЧисло(100000, 999999);

ИмяФайла = Каталог + "\Файл_" + Формат(СлучайноеЧисло, "ЧГ=") + ".txt";

Этот способ можно комбинировать с датой для повышения надежности.

Важные рекомендации для надежности и кроссплатформенности

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

1. Используйте кроссплатформенный разделитель пути

В примерах выше мы использовали символ "\" в качестве разделителя каталогов. Это будет работать на Windows, но вызовет ошибку, если сервер 1С работает под управлением ОС Linux. Чтобы код был универсальным, нужно использовать функцию ПолучитьРазделительПути().

Правильный пример кода:


// Получаем системный разделитель пути ("\" для Windows, "/" для Linux)
Разделитель = ПолучитьРазделительПути();
Каталог = "C:" + Разделитель + "Temp" + Разделитель + "Logs";

ИмяФайла = Каталог + Разделитель + "Файл_" + Формат(Новый УникальныйИдентификатор) + ".txt";

2. Обеспечьте существование каталога

Перед записью файла полезно убедиться, что целевой каталог существует. Если его нет, операция записи вызовет ошибку. Процедура СоздатьКаталог() решит эту проблему — она создаст папку, если ее нет.


КаталогДляЗаписи = "C:\Temp\Logs";
СоздатьКаталог(КаталогДляЗаписи); // Если каталог уже есть, ничего не произойдет

// Далее код записи файла...

3. Обрабатывайте возможные ошибки

Операции с файлами могут завершиться неудачно по разным причинам: нет прав на запись в каталог, закончилось место на диске. Чтобы регламентное задание не "падало" с ошибкой, весь код работы с файлами следует обернуть в конструкцию Попытка...Исключение...КонецПопытки.


Попытка
    Разделитель = ПолучитьРазделительПути();
    Каталог = "C:" + Разделитель + "Temp" + Разделитель + "Logs";
    СоздатьКаталог(Каталог);

    ИмяФайла = Каталог + Разделитель + "Файл_" + Формат(Новый УникальныйИдентификатор) + ".txt";
    
    ТекстовыйДокумент = Новый ТекстовыйДокумент;
    ТекстовыйДокумент.ДобавитьСтроку("Данные для записи.");
    
    // При записи можно указать кодировку, например, UTF-8
    ТекстовыйДокумент.Записать(ИмяФайла, "UTF-8");

Исключение
    // Записываем информацию об ошибке в журнал регистрации
    // чтобы потом можно было проанализировать проблему
    ТекстОшибки = "Не удалось записать файл. Причина: " + ОписаниеОшибки();
    ЗаписьЖурналаРегистрации("МояОбработка.ОшибкаЗаписи", УровеньЖурналаРегистрации.Ошибка, , , ТекстОшибки);
КонецПопытки;

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

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

← На главную