Запись текста в файл на встроенном языке 1С:Предприятия 8.3

· 9 мин

Содержание

Чтобы записать строку в текстовый файл в 1С, создайте объект ЗаписьТекста с путём к файлу и кодировкой, вызовите ЗаписатьСтроку() и обязательно Закрыть(). Три строки кода — и файл на диске. Без Закрыть() последние данные могут остаться в буфере и не попасть в файл.

Типичная ситуация: бухгалтер просит выгрузить список контрагентов для банка в txt, а банк ждёт UTF-8 без BOM. Или нужно вести собственный лог обмена, дописывая по строке в конец. Всё это решается одним объектом платформы 1С:Предприятие 8.3, если знать про кодировки, режимы открытия и то, на каком компьютере выполняется код.

Записать строку в файл через ЗаписьТекста: базовый пример

ЗаписьТекста — основной инструмент платформы для последовательной записи текста. Он пишет файл потоком, не держит всё содержимое в памяти и работает с любым объёмом.

Минимальный рабочий пример:

ИмяФайла = "C:\Выгрузки\контрагенты.txt";

Запись = Новый ЗаписьТекста(ИмяФайла, КодировкаТекста.UTF8);
Запись.ЗаписатьСтроку("ИНН;Наименование");
Запись.ЗаписатьСтроку("7701234567;ООО Ромашка");
Запись.Закрыть();

Параметры конструктора по порядку:

  1. ИмяФайла — полный путь. Каталог должен существовать заранее.
  2. Кодировка — значение КодировкаТекста или строка вида "windows-1251".
  3. РазделительСтрок — какой символ в ваших строках считать переводом строки. По умолчанию ПС.
  4. Дописывать — Истина, чтобы писать в конец существующего файла.
  5. РазделительСтрокВФайле — что записывать в файл как конец строки. По умолчанию ВК + ПС.

Записать или ЗаписатьСтроку

МетодЧто делаетКогда нужен
ЗаписатьСтроку(Строка)пишет текст и добавляет перевод строкипострочные выгрузки, CSV, логи
Записать(Строка)пишет текст без перевода строкисклейка одной строки из частей, фиксированный формат

Если строка уже содержит Символы.ПС, платформа заменит их на разделитель из пятого параметра. Для файла под Linux-систему, где ждут только LF, передайте Символы.ПС пятым параметром.

Запись = Новый ЗаписьТекста(ИмяФайла, "UTF-8", , , Символы.ПС);

Вариант через ТекстовыйДокумент

Для небольших файлов удобен ТекстовыйДокумент: строки копятся в памяти, файл пишется одной командой.

Текст = Новый ТекстовыйДокумент;
Текст.ДобавитьСтроку("Первая строка");
Текст.ДобавитьСтроку("Вторая строка");
Текст.Записать(ИмяФайла, КодировкаТекста.UTF8);

Закрывать ничего не нужно. Зато весь текст живёт в оперативной памяти, поэтому для сотен тысяч строк этот способ не годится.

Кодировка файла: UTF-8, BOM и windows-1251

Чаще всего проблемы с записью строки в файл связаны не с кодом, а с тем, что принимающая программа видит «кракозябры». Кодировку выбирают под получателя, а не под 1С.

ЗначениеЧто получитсяКому подходит
КодировкаТекста.UTF8UTF-8 с BOM (три служебных байта в начале)Блокнот, Excel, большинство Windows-программ
КодировкаТекста.ANSIсистемная кодировка ОС (на русской Windows — windows-1251)старые банк-клиенты, DOS-наследие
"windows-1251"явно cp1251 независимо от ОСкогда сервер на Linux, а получатель ждёт 1251
КодировкаТекста.OEMcp866консольные утилиты, bat-файлы с кириллицей
КодировкаТекста.UTF16UTF-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:\Выгрузки");
КонецЕсли;
Диагностика: выберите симптом

Буфер обмена и временные файлы как альтернатива

Иногда файл как таковой не нужен: пользователю надо вставить текст в письмо или в поле на сайте.

Скопировать строку в буфер обмена

Простого синхронного метода «записать строку в буфер» у платформы долго не было. Варианты:

  1. Показать текст и дать скопировать. ТекстовыйДокумент с методом Показать() откроет окно, пользователь нажмёт Ctrl+A, Ctrl+C. Работает везде, включая веб-клиент.
  2. Поле формы с текстом. Строка выводится в многострочное поле только для просмотра — так же копируется вручную.
  3. 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 с методом ОткрытьФайл. Он сам расставит экранирование и кавычки, собирать JSON строками вручную не нужно.
Почему файл открывается в Excel одной колонкой?
Excel на русской Windows ждёт разделитель ;, а не запятую. Если запятая обязательна, откройте файл через импорт данных и укажите разделитель вручную.
Как дописать строку не в конец, а в начало файла?
Напрямую никак: файл дописывается только в конец. Прочитайте старое содержимое через ЧтениеТекста, запишите новую строку, затем старый текст, и сохраните файл заново.
Работает ли запись в файл в мобильном приложении 1С?
Работает в каталоге документов приложения, путь к нему возвращает КаталогДокументов(). Произвольные пути на устройстве недоступны.