Мы рассмотрим, как эффективно работать с текстовыми файлами на сервере 1С, создавая их во временном каталоге, записывая данные, считывая содержимое и обеспечивая корректное удаление. Это критически важная задача для многих серверных обработок, регламентных заданий, операций обмена данными между базами 1С и приложениями и других фоновых процессов, где требуется временное хранение текстовой информации — для этого подойдет выгрузка данных из 1С во внешние файлы CSV и JSON.
При работе в среде 1С:Предприятие версии 8.3 и выше, особенно при использовании управляемых форм, возникает необходимость выполнять некоторые операции, такие как работа с файлами, непосредственно на сервере. Это позволяет избежать проблем с производительностью, безопасностью и доступностью файловой системы на клиентской машине. Давайте разберем основные подходы к решению этой задачи.
Прежде чем погружаться в код, очень важно понять фундаментальное различие между клиентскими и серверными операциями с файлами в 1С. Когда вы работаете в толстом или тонком клиенте, любые операции с файлами по умолчанию выполняются на том компьютере, где запущен клиентское приложение. Однако, если требуется выполнить действие в рамках регламентного задания, фонового процесса или просто обеспечить централизованную обработку данных, необходимо использовать серверные процедуры и функции.
Ключевой момент: объект ПолеТекстовогоДокумента, который часто ассоциируется с созданием текстовых файлов, на самом деле является элементом управления интерфейса и предназначен для работы с текстовыми документами непосредственно в форме клиента. Он не подходит для серверных операций, где нет активного пользовательского интерфейса. При попытке использовать его на сервере мы столкнемся с ошибками, так как серверу просто неоткуда взять этот элемент управления.
Для серверных операций с текстовыми файлами в 1С мы используем специализированные объекты, которые не зависят от интерфейса и могут быть вызваны в любом серверном контексте. Это объекты ЗаписьТекста и ЧтениеТекста.
Кроме того, нам потребуется определить местоположение для временного файла. Функция КаталогВременныхФайлов() идеально подходит для этих целей. Она возвращает путь к каталогу временных файлов текущего сеанса или процесса на сервере (если вызов происходит на сервере) или на клиенте (если вызов происходит на клиенте). Это обеспечивает, что мы всегда работаем с доступным и корректным путем.
Чтобы создать текстовый файл и записать в него данные на сервере 1С, мы будем использовать объект ЗаписьТекста. Давайте рассмотрим пошаговый процесс.
Сначала нам нужно определить полное имя файла, включая его путь. Для этого мы объединим путь к временному каталогу, полученный с помощью КаталогВременныхФайлов(), с именем нашего файла. Критически важно придумывать уникальные имена для временных файлов, особенно в многопользовательской среде или при частом запуске регламентных заданий. Это поможет избежать конфликтов, когда несколько процессов одновременно пытаются создать или изменить файл с одним и тем же именем. Для генерации уникального имени мы можем использовать объект Новый УникальныйИдентификатор().
Пример генерации уникального имени файла:
ИмяФайла = КаталогВременныхФайлов() + "МойТекстовыйФайл_" + Новый УникальныйИдентификатор() + ".txt";
После того как мы получили уникальное имя файла, мы можем приступить к его созданию и записи данных. Объект ЗаписьТекста инициализируется с полным путем к файлу и кодировкой текста. Наиболее универсальной и рекомендуемой кодировкой является КодировкаТекста.UTF8, которая поддерживает широкий спектр символов. Подобные механизмы часто лежат в основе задач, когда требуется выгрузка внешних отчетов и обработок в файлы для их последующего хранения или передачи.
Вот пример кода для создания файла и записи в него одной строки текста:
// Определяем полное имя файла в каталоге временных файлов
ИмяФайла = КаталогВременныхФайлов() + "ПримерЗаписиФайла_" + Новый УникальныйИдентификатор() + ".txt";
// Создаем объект для записи текста в файл, указываем кодировку UTF8
Запись = Новый ЗаписьТекста(ИмяФайла, КодировкаТекста.UTF8);
// Записываем строку в файл
Запись.ЗаписатьСтроку("Привет, это тестовая строка, записанная на сервере 1С!");
Запись.ЗаписатьСтроку("Это вторая строка в файле.");
// Обязательно закрываем файл после завершения записи
Запись.Закрыть();
Сообщить("Файл успешно создан и записан по пути: " + ИмяФайла);
В этом примере мы используем метод ЗаписатьСтроку() для добавления текста в файл. Каждый вызов этого метода добавляет новую строку. Очень важно после завершения всех операций записи вызвать метод Закрыть() для объекта ЗаписьТекста. Это гарантирует, что все буферизированные данные будут записаны на диск, а сам файл будет корректно закрыт и освобожден для других операций.
После того как файл создан и в него записаны данные, нам может потребоваться прочитать его содержимое. Для этого мы воспользуемся объектом ЧтениеТекста.
Объект ЧтениеТекста также инициализируется полным путем к файлу и его кодировкой. Убедитесь, что вы используете ту же кодировку, в которой файл был записан, чтобы избежать проблем с отображением символов.
Вот пример кода для чтения всего содержимого файла:
// Предполагаем, что ИмяФайла содержит путь к ранее созданному файлу
// Если файл был создан в предыдущем шаге, используем его имя:
// ИмяФайла = КаталогВременныхФайлов() + "ПримерЗаписиФайла_" + Новый УникальныйИдентификатор() + ".txt"; // (если нужно создать новый)
// Создаем объект для чтения текста из файла
Чтение = Новый ЧтениеТекста(ИмяФайла, КодировкаТекста.UTF8);
// Читаем все содержимое файла целиком
СодержимоеФайла = Чтение.Прочитать();
// Обязательно закрываем файл после завершения чтения
Чтение.Закрыть();
Сообщить("Содержимое файла '" + ИмяФайла + "':");
Сообщить(СодержимоеФайла);
Метод Прочитать() возвращает весь текст файла одной строкой. Если вам нужно читать файл построчно (например, для обработки больших файлов или когда каждая строка представляет отдельную запись), вы можете использовать метод ПрочитатьСтроку() в цикле. Это стандартный подход, когда реализуется импорт данных из текстовых форматов для первоначального заполнения базы:
// ... (инициализация ЧтениеТекста) ...
МассивСтрокИзФайла = Новый Массив;
Пока Истина Цикл
СтрокаИзФайла = Чтение.ПрочитатьСтроку();
Если СтрокаИзФайла = Неопределено Тогда
// Достигнут конец файла
Прервать;
КонецЕсли;
МассивСтрокИзФайла.Добавить(СтрокаИзФайла);
КонецЦикла;
Чтение.Закрыть();
Сообщить("Файл прочитан построчно. Количество строк: " + МассивСтрокИзФайла.Количество());
Для Каждого Стр Из МассивСтрокИзФайла Цикл
Сообщить(Стр);
КонецЦикла;
Метод ПрочитатьСтроку() возвращает Неопределено, когда достигнут конец файла, что позволяет удобно организовать цикл чтения.
После того как мы закончили работу с временным файлом, очень важно удалить его. Если этого не делать, временные каталоги на сервере будут засоряться, что может привести к нехватке дискового пространства и снижению производительности системы.
Для удаления файлов в 1С используется глобальная функция УдалитьФайлы(). Она принимает в качестве параметра либо полное имя файла, либо шаблон имени файла (например, "C:\Temp\*.txt" для удаления всех txt-файлов в папке).
Пример удаления файла:
// Предполагаем, что ИмяФайла содержит путь к файлу, который нужно удалить
Попытка
УдалитьФайлы(ИмяФайла);
Сообщить("Файл '" + ИмяФайла + "' успешно удален.");
Исключение
Сообщить("Ошибка при удалении файла '" + ИмяФайла + "': " + ОписаниеОшибки());
КонецПопытки;
Мы рекомендуем всегда оборачивать операции удаления в блок Попытка...Исключение, так как файл может быть уже удален, заблокирован другим процессом или возникнут иные проблемы доступа. Обработка исключений сделает ваш код более надежным.
Давайте объединим все рассмотренные шаги в один полноценный пример, который включает создание, запись, чтение и удаление файла, а также предусматривает обработку возможных ошибок. Такой подход является образцом хорошей практики при разработке.
Мы создадим серверную функцию, которая инкапсулирует логику получения содержимого файла.
// Процедура, демонстрирующая полный цикл работы с файлом
Процедура ПримерРаботыСФайломНаСервере() Экспорт
Перем ПолноеИмяФайла;
Попытка
// 1. Создаем уникальное имя файла
ПолноеИмяФайла = КаталогВременныхФайлов() + Новый УникальныйИдентификатор() + ".txt";
Сообщить("Будет создан файл: " + ПолноеИмяФайла);
// 2. Записываем данные в файл
ЗаписьТекста = Новый ЗаписьТекста(ПолноеИмяФайла, КодировкаТекста.UTF8);
ЗаписьТекста.ЗаписатьСтроку("Эта строка записана в файл на сервере.");
ЗаписьТекста.ЗаписатьСтроку("Вторая строка для проверки построчного чтения.");
// Можем также записать данные из массива строк
МассивСтрокДляЗаписи = Новый Массив;
МассивСтрокДляЗаписи.Добавить("Третья строка из массива.");
МассивСтрокДляЗаписи.Добавить("Четвертая строка, также из массива.");
Для Каждого СтрокаИзМассива Из МассивСтрокДляЗаписи Цикл
ЗаписьТекста.ЗаписатьСтроку(СтрокаИзМассива);
КонецЦикла;
ЗаписьТекста.Закрыть();
Сообщить("Файл создан и данные записаны.");
// 3. Считываем содержимое файла
ТекстИзФайла = ПолучитьСодержимоеФайлаСервер(ПолноеИмяФайла);
Сообщить("Содержимое файла:");
Сообщить(ТекстИзФайла);
Исключение
Сообщить("Произошла ошибка в процессе работы с файлом: " + ОписаниеОшибки());
КонецПопытки;
// 4. Удаляем файл (выполняется вне блока Попытка, чтобы гарантировать удаление
// даже если при чтении произошла ошибка, но файл был создан)
Если ЗначениеЗаполнено(ПолноеИмяФайла) Тогда
Попытка
УдалитьФайлы(ПолноеИмяФайла);
Сообщить("Файл '" + ПолноеИмяФайла + "' успешно удален.");
Исключение
Сообщить("Ошибка при удалении файла '" + ПолноеИмяФайла + "': " + ОписаниеОшибки());
КонецПопытки;
КонецЕсли;
КонецПроцедуры
// Функция на сервере для получения содержимого файла
// Может быть вызвана из других серверных процедур
Функция ПолучитьСодержимоеФайлаСервер(ИмяФайла) Экспорт
Перем РезультатЧтения;
РезультатЧтения = ""; // Инициализируем пустой строкой
Если Не СтрНайти(ИмяФайла, КаталогВременныхФайлов()) > 0 Тогда
// Дополнительная проверка на безопасность: не даем читать произвольные файлы
Сообщить("Попытка чтения файла из недопустимого каталога: " + ИмяФайла);
Возврат РезультатЧтения;
КонецЕсли;
Попытка
ЧтениеТекста = Новый ЧтениеТекста(ИмяФайла, КодировкаТекста.UTF8);
РезультатЧтения = ЧтениеТекста.Прочитать();
ЧтениеТекста.Закрыть();
Исключение
Сообщить("Ошибка при чтении файла '" + ИмяФайла + "': " + ОписаниеОшибки());
// В случае ошибки возвращаем пустую строку или обрабатываем иначе
РезультатЧтения = "";
КонецПопытки;
Возврат РезультатЧтения;
КонецФункции
Обратите внимание, что в данном примере функция ПолучитьСодержимоеФайлаСервер() вынесена отдельно и помечена как Экспорт. Это позволяет вызывать ее из других серверных процедур или модулей. Кроме того, мы добавили небольшую проверку на безопасность, чтобы убедиться, что пытаемся читать файл именно из временного каталога.
Важные моменты в комплексном примере:
Попытка...Исключение вокруг всех файловых операций критически важно. Это позволяет корректно реагировать на ситуации, когда файл не может быть создан (нет прав), не может быть прочитан (не существует или заблокирован) или не может быть удален.
Закрыть() для объектов ЗаписьТекста и ЧтениеТекста. Это освобождает файловые дескрипторы и гарантирует сохранение данных.
ПолноеИмяФайла заполнена, чтобы избежать ошибок при удалении несуществующего или неопределенного пути.
ПолучитьСодержимоеФайлаСервер) улучшает читаемость и повторное использование кода.
КодировкаТекста.UTF8, вы можете использовать другие кодировки, такие как КодировкаТекста.ANSI (для совместимости с некоторыми старыми системами) или КодировкаТекста.UTF16. Выбор кодировки зависит от требований к данным и целевой системе. Однако, UTF8 является наиболее универсальной.
ДвоичныеДанные, ЗаписьДвоичныхДанных и ЧтениеДвоичныхДанных. Эти объекты позволяют работать с файлами на уровне байтов.
ЗаписьXML, ЧтениеXML, ЗаписьJSON, ЧтениеJSON (удобнее через универсальный экспорт документов в XML, JSON, TXT и CSV). Они упрощают сериализацию данных, а для более сложных преобразований можно использовать модуль «Трансформер» для конвертации JSON/XML/CSV/TOON.
Мы подробно разобрали основные подходы к работе с текстовыми файлами на сервере 1С, обеспечивая надежное создание, запись, чтение и удаление. Используя объекты ЗаписьТекста и ЧтениеТекста в сочетании с функцией КаталогВременныхФайлов() и правильной обработкой ошибок, вы сможете создавать robust-серверные решения, способные эффективно взаимодействовать с файловой системой. Не забывайте про важность уникальных имен файлов и своевременной очистки временных данных!