Как в 1С записать текстовый файл в кодировке UTF-16LE UNIX без BOM?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

При интеграции 1С с внешним программным обеспечением разработчики часто сталкиваются с жесткими требованиями к форматам файлов обмена. Одним из таких примеров является работа со специализированным софтом для проектирования натяжных потолков (например, Easy Ceiling). Файлы фактур с расширением .fact содержат текстовые данные, которые должны быть записаны строго в кодировке UTF-16LE, с разделителями строк в стиле UNIX (LF) и, что самое важное, без маркера последовательности байтов (BOM).

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

Выясняем причину: нюансы платформы 1С при работе с BOM

Маркер последовательности байтов (Byte Order Mark, BOM) — это специальный символ в начале текстового файла (для UTF-16LE это байты FF FE), указывающий на порядок байтов при чтении. Многие UNIX-системы и специализированные парсеры (например, импорт в Easy Ceiling) не ожидают увидеть эти байты и выдают ошибку при попытке прочитать файл.

В 1С методы записи файлов напрямую по пути к файлу на диске, такие как ТекстовыйДокумент.Записать(ИмяФайла...) или ЗаписьТекста(ИмяФайла...), всегда принудительно добавляют BOM для кодировок UTF-8 и UTF-16. В синтаксисе этих методов при указании пути к файлу просто отсутствует параметр управления BOM. Возможность отключить BOM (параметр ЗаписатьBOM = Ложь) появляется только тогда, когда запись производится через поток данных (файловый или в памяти), либо при использовании специализированных методов преобразования двоичных данных.

Ниже мы подробно разберем три практических способа решения этой проблемы.

Способ №1: Использование файлового потока (Классическое решение для 1С 8.3)

Рассмотрим метод, к которому пришел автор темы. Если нам необходимо использовать объект ТекстовыйДокумент для формирования файла, мы не можем записывать его напрямую по пути. Вместо этого мы создаем файловый поток, а затем передаем его в метод Записать() текстового документа. В этом случае нам становится доступен четвертый параметр метода, отвечающий за запись BOM.

Разберем пример реализации этого метода по шагам:


// 1. Указываем путь к целевому файлу
ПутьКФайлу = "F:\Users\admin\Desktop\Factura.fact";

// 2. Создаем файловый поток в режиме создания нового файла
Поток = Новый ФайловыйПоток(ПутьКФайлу, РежимОткрытияФайла.Создать);

// 3. Создаем текстовый документ и наполняем его данными
ТекстовыйДокумент = Новый ТекстовыйДокумент;
ТекстовыйДокумент.ДобавитьСтроку("false");
ТекстовыйДокумент.ДобавитьСтроку("0");
ТекстовыйДокумент.ДобавитьСтроку("1256");
ТекстовыйДокумент.ДобавитьСтроку("Перламутр 305");

// 4. Записываем текстовый документ в поток. 
// Параметры метода Записать:
// - Поток (объект ФайловыйПоток)
// - Кодировка ("UTF-16LE")
// - Разделитель строк (Символы.ПС — это UNIX-символ LF)
// - ЗаписатьBOM (Ложь — отключает принудительную запись BOM)
ТекстовыйДокумент.Записать(Поток, "UTF-16LE", Символы.ПС, Ложь);

// 5. Закрываем поток для освобождения файла операционной системой
Поток.Закрыть();

Преимущества: Этот способ полностью решает проблему, сохраняя привычную структуру работы с объектом ТекстовыйДокумент.

Способ №2: Самый лаконичный и современный метод (для платформ 1С 8.3.10 и новее)

Если в вашей конфигурации не требуется построчное формирование файла на диске, а весь текст можно предварительно собрать в одну переменную, то лучшим решением будет использование глобальной функции ПолучитьДвоичныеДанныеИзСтроки(). Этот метод позволяет получить чистый массив байтов в нужной кодировке без BOM, который затем можно мгновенно сохранить в файл.

Посмотрим на пример кода:


// Формируем итоговый текст. Символы.ПС — это LF (UNIX-перенос строки)
ТекстФайла = "false" + Символы.ПС 
           + "0" + Символы.ПС 
           + "1256" + Символы.ПС 
           + "Перламутр 305";

// Получаем двоичные данные строки в UTF-16LE без BOM (третий параметр — Ложь)
ДвоичныеДанные = ПолучитьДвоичныеДанныеИзСтроки(ТекстФайла, "UTF-16LE", Ложь);

// Записываем полученные двоичные данные напрямую в файл на диске
ДвоичныеДанные.Записать("F:\Users\admin\Desktop\Factura.fact");

Преимущества: Минимальное количество строк кода. Нет необходимости вручную создавать, открывать и закрывать потоки данных — платформа берет эти низкоуровневые операции на себя.

Способ №3: Оптимальный метод для больших файлов (Построчная запись)

Проанализируем ситуацию, когда данных для экспорта очень много (например, весь справочник номенклатуры с характеристиками). Если мы будем формировать одну гигантскую текстовую строку в памяти (Способ №2) или использовать ТекстовыйДокумент (Способ №1), программа может исчерпать доступную оперативную память компьютера, что приведет к аварийному завершению работы 1С.

Для оптимизации расхода памяти мы рекомендуем использовать построчную запись через объект ЗаписьТекста, инициализированный поверх файлового потока:


ПутьКФайлу = "F:\Users\admin\Desktop\Factura.fact";

// Создаем файловый поток
Поток = Новый ФайловыйПоток(ПутьКФайлу, РежимОткрытияФайла.Создать);

// Используем конструктор ЗаписьТекста на основании потока.
// Передаем параметры: Поток, Кодировка, РазделительСтрок, КонвертироватьСимволы, ЗаписатьBOM
Запись = Новый ЗаписьТекста(Поток, "UTF-16LE", Символы.ПС, , Ложь);

// Начинаем обход данных (например, выборки из справочника Номенклатура)
Выборка = Справочники.Номенклатура.Выбрать();
Пока Выборка.Следующий() Цикл
    // Записываем каждую строку по отдельности
    Запись.ЗаписатьСтроку(Выборка.Наименование);
КонецЦикла;

// Закрываем запись (поток при этом закроется автоматически)
Запись.Закрыть();

Преимущества: Данные порциями сбрасываются на жесткий диск. Потребление оперативной памяти остается минимальным и стабильным независимо от размера выгружаемого файла.

Резюме

Мы рассмотрели особенности работы платформы 1С:Предприятие с кодировками семейства UTF. Для решения проблемы с нежелательным BOM и UNIX-разделителями строк используйте:

  1. Файловые потоки совместно с ТекстовыйДокумент для быстрого исправления существующего кода.
  2. Метод ПолучитьДвоичныеДанныеИзСтроки() для лаконичной и быстрой записи небольших файлов.
  3. Объект ЗаписьТекста поверх файлового потока для высоконагруженных систем и больших объемов данных.
← На главную