Как правильно записывать все строки из цикла в текстовый файл в 1С?

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

При разработке алгоритмов выгрузки данных программисты часто сталкиваются с ситуацией, когда вместо ожидаемого списка строк в итоговый файл попадает только одна — самая последняя. Это происходит из-за типичной логической ошибки: перезаписи переменной на каждой итерации цикла вместо добавления (аккумуляции) новых данных. Рассмотрим подробно, почему так происходит и как реализовать корректную запись данных несколькими способами.

Проблема: Почему сохраняется только последняя строка?

Разберем ситуацию на примере исходного кода. Когда внутри цикла Пока Выборка.Следующий() используется конструкция Данные2 = выборка.данные3;, система на каждом шаге стирает старое значение переменной Данные2 и записывает туда новое. В итоге после завершения цикла в переменной остается только результат последней итерации.

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

Способ 1. Накопление строк в переменной с использованием символов переноса

Проанализируем самый простой вариант, когда нам нужно собрать одну большую строку и передать её куда-то дальше. Чтобы данные не склеивались в одну «кашу», мы должны использовать специальные символы переноса строки.

Рассмотрим пример кода, где мы добавляем проверку на заполненность, чтобы не начинать файл с пустой строки:


Данные2 = ""; 
Пока Выборка.Следующий() Цикл 
    Если ЗначениеЗаполнено(Данные2) Тогда 
        // Добавляем символ переноса строки перед новой порцией данных
        Данные2 = Данные2 + Символы.ПС + Выборка.Данные3; 
    Иначе 
        // Если это первая итерация, просто присваиваем значение
        Данные2 = Выборка.Данные3; 
    КонецЕсли; 
КонецЦикла;

В данном примере Символы.ПС — это системная константа, обозначающая перевод строки. В некоторых случаях (например, для корректного отображения в старом «Блокноте» Windows) может потребоваться Символы.ВКПС (возврат каретки и перевод строки).

Способ 2. Использование объекта ТекстовыйДокумент

Объект ТекстовыйДокумент удобен тем, что он инкапсулирует в себе логику работы со строками. Нам не нужно вручную добавлять Символы.ПС, так как метод ДобавитьСтроку() делает это автоматически.

Выясним, как изменить структуру функции, чтобы цикл находился внутри процесса формирования документа:


ТД = Новый ТекстовыйДокумент;
Данные1 = "Заголовок или постоянная часть";

Выборка = РезультатЗапроса.Выбрать();
Пока Выборка.Следующий() Цикл
    // Формируем строку для каждой итерации
    ТекущаяСтрока = Данные1 + ";" + Выборка.Данные3;
    // Добавляем её в объект текстового документа
    ТД.ДобавитьСтроку(ТекущаяСтрока);
КонецЦикла;

// Сохраняем весь накопленный результат на диск
ТД.Записать(ИмяФайла, КодировкаТекста.UTF8);

Важный момент: использование ТекстовыйДокумент оправдано для небольших и средних объемов данных. Поскольку этот объект хранит весь текст в оперативной памяти, при выгрузке сотен тысяч строк программа может начать потреблять слишком много ресурсов.

Способ 3. Потоковая запись с помощью ЗаписьТекста (Оптимальный метод)

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

Разберем по шагам, как реализовать дозапись в файл:

  1. Создаем объект ЗаписьТекста, указывая путь к файлу и кодировку.
  2. Используем параметр Дописывать = Истина, если нужно добавить данные в конец существующего файла.
  3. В цикле вызываем метод ЗаписатьСтроку().
  4. Обязательно закрываем объект методом Закрыть(), чтобы зафиксировать изменения на диске.

ПутьКФайлу = "C:\temp\log.txt";
// Третий параметр "Истина" включает режим дозаписи
Запись = Новый ЗаписьТекста(ПутьКФайлу, КодировкаТекста.UTF8, , Истина);

Пока Выборка.Следующий() Цикл
    ТекстДляЗаписи = Строка(Выборка.Данные3);
    Запись.ЗаписатьСтроку(ТекстДляЗаписи);
КонецЦикла;

Запись.Закрыть();

Профессиональные рекомендации по оптимизации

Рассмотрим подробнее ситуации, когда стандартных методов может быть недостаточно:

1. Использование массива для сборки строк. Если вам все же нужно собрать данные в одну переменную-строку, но итераций очень много (тысячи), классическая конкатенация через + будет работать медленно. Проанализируем более эффективный подход через Массив:


МассивСтрок = Новый Массив;
Пока Выборка.Следующий() Цикл
    МассивСтрок.Добавить(Строка(Выборка.Данные3));
КонецЦикла;
ИтоговыйТекст = СтрСоединить(МассивСтрок, Символы.ПС);

Этот метод работает в разы быстрее, так как 1С не пересоздает строку в памяти на каждом шаге цикла.

2. Типизация данных. Всегда явно преобразуйте значения к строке, используя функцию Строка(). Если в Выборка.Данные3 окажется число (например, 1 000), 1С может добавить неразрывный пробел в качестве разделителя разрядов, что нарушит структуру CSV-файла или XML. Для чисел лучше использовать Формат(Значение, "ЧГ=0").

3. Формирование XML. Если переменная называется ТекстXML, как в исходном вопросе, лучше вообще отказаться от ручной склейки строк. Для этих целей в платформе есть специализированный объект ЗаписьXML. Он автоматически следит за корректностью спецсимволов (заменяет & на & и т.д.) и закрытием тегов, что гарантирует валидность вашего файла.

Таким образом, выбор метода зависит от вашей задачи: для простых отчетов подойдет ТекстовыйДокумент, для высоконагруженных систем — ЗаписьТекста, а для сборки строк в памяти — Массив и СтрСоединить.

← На главную