Запись текста в файл на встроенном языке 1С:Предприятия 8.3
Содержание
Чтобы записать строку в текстовый файл в 1С, создайте объект ЗаписьТекста с путём к файлу и кодировкой, вызовите ЗаписатьСтроку() и обязательно Закрыть(). Три строки кода — и файл на диске. Без Закрыть() последние данные могут остаться в буфере и не попасть в файл.
Типичная ситуация: бухгалтер просит выгрузить список контрагентов для банка в txt, а банк ждёт UTF-8 без BOM. Или нужно вести собственный лог обмена, дописывая по строке в конец. Всё это решается одним объектом платформы 1С:Предприятие 8.3, если знать про кодировки, режимы открытия и то, на каком компьютере выполняется код.
Записать строку в файл через ЗаписьТекста: базовый пример
ЗаписьТекста — основной инструмент платформы для последовательной записи текста. Он пишет файл потоком, не держит всё содержимое в памяти и работает с любым объёмом.
Минимальный рабочий пример:
ИмяФайла = "C:\Выгрузки\контрагенты.txt";
Запись = Новый ЗаписьТекста(ИмяФайла, КодировкаТекста.UTF8);
Запись.ЗаписатьСтроку("ИНН;Наименование");
Запись.ЗаписатьСтроку("7701234567;ООО Ромашка");
Запись.Закрыть();
Параметры конструктора по порядку:
- ИмяФайла — полный путь. Каталог должен существовать заранее.
- Кодировка — значение
КодировкаТекстаили строка вида"windows-1251". - РазделительСтрок — какой символ в ваших строках считать переводом строки. По умолчанию
ПС. - Дописывать —
Истина, чтобы писать в конец существующего файла. - РазделительСтрокВФайле — что записывать в файл как конец строки. По умолчанию
ВК + ПС.
Записать или ЗаписатьСтроку
| Метод | Что делает | Когда нужен |
|---|---|---|
ЗаписатьСтроку(Строка) | пишет текст и добавляет перевод строки | построчные выгрузки, CSV, логи |
Записать(Строка) | пишет текст без перевода строки | склейка одной строки из частей, фиксированный формат |
Если строка уже содержит Символы.ПС, платформа заменит их на разделитель из пятого параметра. Для файла под Linux-систему, где ждут только LF, передайте Символы.ПС пятым параметром.
Запись = Новый ЗаписьТекста(ИмяФайла, "UTF-8", , , Символы.ПС);
Вариант через ТекстовыйДокумент
Для небольших файлов удобен ТекстовыйДокумент: строки копятся в памяти, файл пишется одной командой.
Текст = Новый ТекстовыйДокумент;
Текст.ДобавитьСтроку("Первая строка");
Текст.ДобавитьСтроку("Вторая строка");
Текст.Записать(ИмяФайла, КодировкаТекста.UTF8);
Закрывать ничего не нужно. Зато весь текст живёт в оперативной памяти, поэтому для сотен тысяч строк этот способ не годится.
Кодировка файла: UTF-8, BOM и windows-1251
Чаще всего проблемы с записью строки в файл связаны не с кодом, а с тем, что принимающая программа видит «кракозябры». Кодировку выбирают под получателя, а не под 1С.
| Значение | Что получится | Кому подходит |
|---|---|---|
КодировкаТекста.UTF8 | UTF-8 с BOM (три служебных байта в начале) | Блокнот, Excel, большинство Windows-программ |
КодировкаТекста.ANSI | системная кодировка ОС (на русской Windows — windows-1251) | старые банк-клиенты, DOS-наследие |
"windows-1251" | явно cp1251 независимо от ОС | когда сервер на Linux, а получатель ждёт 1251 |
КодировкаТекста.OEM | cp866 | консольные утилиты, bat-файлы с кириллицей |
КодировкаТекста.UTF16 | UTF-16 | редкие форматы обмена |
КодировкаТекста.ANSI зависит от системы, где выполняется код. На сервере под Linux результат будет другим. Если формат требует 1251 — пишите строку "windows-1251" явно.
Как записать UTF-8 без BOM
BOM ломает разбор у многих сервисов: первое поле CSV читается как \ufeffИНН, а JSON не проходит валидацию. ЗаписьТекста при создании нового файла в UTF-8 метку пишет. Два рабочих приёма.
Приём 1. Через двоичные данные. Начиная с платформы 8.3.9 есть функция ПолучитьДвоичныеДанныеИзСтроки, где третий параметр управляет меткой BOM:
Текст = "ИНН;Наименование" + Символы.ВК + Символы.ПС + "7701234567;ООО Ромашка";
Данные = ПолучитьДвоичныеДанныеИзСтроки(Текст, "UTF-8", Ложь);
Данные.Записать(ИмяФайла);
Приём 2. Создать пустой файл и дописывать. При дозаписи BOM не добавляется. Пустой файл создают в любой однобайтовой кодировке, затем открывают на дозапись в UTF-8:
Запись = Новый ЗаписьТекста(ИмяФайла, КодировкаТекста.ANSI);
Запись.Закрыть();
Запись = Новый ЗаписьТекста(ИмяФайла, "UTF-8", , Истина);
Запись.ЗаписатьСтроку("ИНН;Наименование");
Запись.Закрыть();
💡 Проверить результат проще всего в Notepad++: в строке состояния видно UTF-8 или UTF-8-BOM.
Спецсимволы внутри строки
- 🔹 Табуляция —
Символы.Таб, удобна для TSV-выгрузок. - 🔹 Кавычки в CSV удваивайте:
СтрЗаменить(Значение, """", """"""). - 🔹 Точку с запятой внутри наименования обрамляйте кавычками, иначе столбцы съедут.
- 🔹 Неразрывный пробел
Символы.НППв 1251 записывается, а в OEM превращается в мусор.
Перезаписать файл или дописать строку в конец
Режим задаёт четвёртый параметр конструктора.
| Параметр «Дописывать» | Файла нет | Файл есть |
|---|---|---|
Ложь или не указан | создаётся новый | содержимое удаляется, пишется заново |
Истина | создаётся новый | новые строки добавляются в конец |
Пример простого журнала, куда каждая операция добавляет одну строку:
Процедура ЗаписатьВЛог(ТекстСообщения) Экспорт
ИмяФайла = "C:\Логи\обмен.log";
Строка = Формат(ТекущаяДатаСеанса(), "ДФ='дд.ММ.гггг ЧЧ:мм:сс'") + Символы.Таб + ТекстСообщения;
Запись = Новый ЗаписьТекста(ИмяФайла, КодировкаТекста.UTF8, , Истина);
Запись.ЗаписатьСтроку(Строка);
Запись.Закрыть();
КонецПроцедуры
Дописывать в файл лучше в той же кодировке, в какой он создан. Если начать файл в 1251, а потом дописать в UTF-8, получится смесь, которую ни один редактор корректно не откроет.
Чтобы гарантированно начать файл с чистого листа, достаточно Дописывать = Ложь. Удалять его заранее через УдалитьФайлы не нужно.
На каком компьютере появится файл
Это главный приём, без которого код «работает у разработчика и не работает
у пользователя». Путь C:\Выгрузки\ указывает на диск того компьютера, где исполняется код.
- 🖥️ Модуль формы с директивой
&НаКлиенте, тонкий клиент — файл ляжет на компьютер пользователя. - 🗄️
&НаСервере, общий модуль на сервере, фоновое или регламентное задание — файл ляжет на сервер 1С. В клиент-серверном варианте это отдельная машина. - 🌐 Веб-клиент —
ЗаписьТекстатам недоступна. Текст формируют на сервере и передают пользователю как файл.
Схема для веб-клиента и для случаев, когда файл нужен пользователю, а данные собираются на сервере:
&НаСервере
Функция ПодготовитьФайлНаСервере()
Текст = "ИНН;Наименование" + Символы.ВК + Символы.ПС + "7701234567;ООО Ромашка";
Данные = ПолучитьДвоичныеДанныеИзСтроки(Текст, "UTF-8", Ложь);
Возврат ПоместитьВоВременноеХранилище(Данные, УникальныйИдентификатор);
КонецФункции
&НаКлиенте
Процедура Выгрузить(Команда)
Адрес = ПодготовитьФайлНаСервере();
ПолучитьФайл(Адрес, "контрагенты.csv", Истина);
КонецПроцедуры
С параметром Истина пользователь сам выберет папку в стандартном диалоге сохранения. В новых конфигурациях для этого принято использовать асинхронные аналоги, но принцип тот же: данные идут через временное хранилище.
На сервере код работает от имени пользователя службы агента сервера 1С (по умолчанию USR1CV8). У него должны быть права на запись в целевой каталог. Сетевой путь \\server\share\ тоже проверяется под этой учётной записью, а не под вашей.
Ошибки при записи строки в файл и их обработка
Любая операция с файлом может упасть: диск переполнен, файл открыт в Excel, каталога нет. Оборачивайте запись в Попытка и закрывайте объект в обеих ветках.
Запись = Неопределено;
Попытка
Запись = Новый ЗаписьТекста(ИмяФайла, КодировкаТекста.UTF8);
Для Каждого Строка Из СтрокиВыгрузки Цикл
Запись.ЗаписатьСтроку(Строка);
КонецЦикла;
Запись.Закрыть();
Исключение
Если Запись <> Неопределено Тогда
Запись.Закрыть();
КонецЕсли;
ТекстОшибки = ОписаниеОшибки();
ЗаписьЖурналаРегистрации("Выгрузка в файл", УровеньЖурналаРегистрации.Ошибка, , , ТекстОшибки);
ВызватьИсключение "Не удалось записать файл " + ИмяФайла + ": " + ТекстОшибки;
КонецПопытки;
Если каталога может не быть, создайте его заранее:
Каталог = Новый Файл("C:\Выгрузки");
Если Не Каталог.Существует() Тогда
СоздатьКаталог("C:\Выгрузки");
КонецЕсли;
Буфер обмена и временные файлы как альтернатива
Иногда файл как таковой не нужен: пользователю надо вставить текст в письмо или в поле на сайте.
Скопировать строку в буфер обмена
Простого синхронного метода «записать строку в буфер» у платформы долго не было. Варианты:
- Показать текст и дать скопировать.
ТекстовыйДокументс методомПоказать()откроет окно, пользователь нажмётCtrl+A,Ctrl+C. Работает везде, включая веб-клиент. - Поле формы с текстом. Строка выводится в многострочное поле только для просмотра — так же копируется вручную.
- COM-объект на Windows. Старый приём для тонкого клиента под Windows:
&НаКлиенте
Процедура СкопироватьВБуфер(Текст)
HTML = Новый COMОбъект("htmlfile");
HTML.parentWindow.clipboardData.setData("Text", Текст);
КонецПроцедуры
Приём зависит от компонентов Internet Explorer в системе и не работает на Linux, macOS и в веб-клиенте. В свежих версиях платформы появились собственные асинхронные средства работы с буфером обмена: ищите их в синтакс-помощнике Конфигуратора по слову «буфер».
Временный файл
Если файл нужен на минуту — например, передать его внешней программе или приложить к письму — берите имя через ПолучитьИмяВременногоФайла:
ИмяФайла = ПолучитьИмяВременногоФайла("txt");
Запись = Новый ЗаписьТекста(ИмяФайла, КодировкаТекста.UTF8);
Запись.ЗаписатьСтроку("Временные данные");
Запись.Закрыть();
// ... используем файл ...
УдалитьФайлы(ИмяФайла);
Платформа сама не удаляет такие файлы. Удаляйте их явно после использования, иначе каталог временных файлов на сервере годами копит мусор.
Массовая запись: как не тормозить на сотнях тысяч строк
Сама ЗаписьТекста буферизует вывод и пишет быстро. Тормозит обычно код вокруг неё.
| Подход | Что происходит | Итог |
|---|---|---|
Открыть один раз, ЗаписатьСтроку в цикле, закрыть | один дескриптор файла, буферизация | быстро, память не растёт |
| Открывать и закрывать файл на каждой строке | открытие и сброс на диск каждый раз | в разы медленнее |
Склеивать всё в одну строку Текст = Текст + ... | строка копируется при каждом сложении | память и время растут квадратично |
Копить в массив и СтрСоединить | одно соединение в конце | быстро для средних объёмов |
ТекстовыйДокумент.ДобавитьСтроку | всё в памяти до записи | удобно, но не для миллионов строк |
Практические правила:
- ⚡ Данные получайте одним запросом и обходите
Выборка.Следующий(), не обращаясь к реквизитам через точку внутри цикла. - ⚡ Число в строку переводите через
Формат(Сумма, "ЧГ=0; ЧРД=."): без формата появятся неразрывные пробелы между разрядами и запятая вместо точки. - ⚡ Для промежуточного результата используйте массив строк и
СтрСоединить(МассивСтрок, Символы.ВК + Символы.ПС)— функция есть в платформе с 8.3.6. - ⚡ Тяжёлую выгрузку запускайте в фоновом задании, чтобы не держать форму пользователя.
Пример выгрузки из запроса:
Запрос = Новый Запрос(
"ВЫБРАТЬ
| Контрагенты.ИНН КАК ИНН,
| Контрагенты.Наименование КАК Наименование
|ИЗ
| Справочник.Контрагенты КАК Контрагенты
|ГДЕ
| НЕ Контрагенты.ЭтоГруппа");
Выборка = Запрос.Выполнить().Выбрать();
Запись = Новый ЗаписьТекста(ИмяФайла, КодировкаТекста.UTF8);
Запись.ЗаписатьСтроку("ИНН;Наименование");
Пока Выборка.Следующий() Цикл
Наименование = СтрЗаменить(Выборка.Наименование, """", """""");
Запись.ЗаписатьСтроку(Выборка.ИНН + ";""" + Наименование + """");
КонецЦикла;
Запись.Закрыть();
Наименование здесь обрамлено кавычками, а кавычки внутри него удвоены — такой CSV корректно откроется в Excel, даже если в названии есть точка с запятой.
Частые вопросы
Можно ли записать строку в файл в 1С без создания объекта?
ПолучитьДвоичныеДанныеИзСтроки(Текст, "UTF-8").Записать(ИмяФайла). Удобно для коротких текстов, например для JSON-ответа.Как записать в файл JSON, а не обычный текст?
ЗаписьJSON с методом ОткрытьФайл. Он сам расставит экранирование и кавычки, собирать JSON строками вручную не нужно.Почему файл открывается в Excel одной колонкой?
;, а не запятую. Если запятая обязательна, откройте файл через импорт данных и укажите разделитель вручную.Как дописать строку не в конец, а в начало файла?
ЧтениеТекста, запишите новую строку, затем старый текст, и сохраните файл заново.Работает ли запись в файл в мобильном приложении 1С?
КаталогДокументов(). Произвольные пути на устройстве недоступны.