Как правильно заменить строку в текстовом файле с помощью 1С?

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

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

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

Простой способ: использование объекта `ТекстовыйДокумент`

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

Стандартный алгоритм замены строки выглядит следующим образом:

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

Посмотрим на пример кода, который решает эту задачу:


// Путь к файлу
запФайл = "C:\Temp\mydata.txt";
// Номер строки для замены (нумерация с 1)
стрЗап = 15; 
// Новая строка, которую нужно записать (например, в формате JSON)
строкЖС = "{""id"": 123, ""value"": ""Новые данные""}";

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

// Заменяем строку
ЗаписьДанных.ЗаменитьСтроку(стрЗап, строкЖС);

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

Сообщить("Строка " + стрЗап + " в файле " + запФайл + " успешно заменена!");

Возможные проблемы и их решение

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

Проблема почти всегда кроется не в методах 1С, а в данных, которые мы пытаемся записать. Наиболее вероятная причина такого поведения — некорректно сформированная заменяющая строка (в нашем примере — переменная строкЖС).

Что нужно проверить:

Таким образом, если вы столкнулись с аномальным поведением при записи, в первую очередь тщательно проверьте данные, которые вы записываете.

Альтернативный способ: построчная обработка для больших файлов

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

Для таких случаев существует более производительный подход — последовательная построчная обработка с использованием объектов ЧтениеТекста и ЗаписьТекста. Этот метод не имеет прямого аналога ЗаменитьСтроку(), поэтому логику придется реализовать самостоятельно.

Алгоритм построчной замены:

  1. Открыть исходный файл для чтения через ЧтениеТекста.
  2. Создать новый временный файл для записи через ЗаписьТекста.
  3. В цикле считывать строку из исходного файла.
  4. Проверять номер текущей строки. Если это строка, которую нужно заменить, — записываем во временный файл новое значение.
  5. Если это любая другая строка — записываем во временный файл ее оригинальное значение.
  6. После окончания цикла закрыть оба объекта (чтения и записи).
  7. Удалить исходный файл.
  8. Переименовать временный файл, дав ему имя исходного.

Этот подход потребляет минимум оперативной памяти, так как в каждый момент времени в ней находится только одна строка.

Рассмотрим пример реализации этого алгоритма:


// Исходные данные
ИмяИсходногоФайла = "C:\temp\big_data.log";
ИмяВременногоФайла = "C:\temp\big_data_temp.log";
НомерСтрокиДляЗамены = 347; // Номер строки для замены
НоваяСтрока = "2023-10-27 15:00:00; INFO; Операция успешно завершена";

Чтение = Неопределено;
Запись = Неопределено;

Попытка
    // 1. Открываем файлы для чтения и записи
    Чтение = Новый ЧтениеТекста(ИмяИсходногоФайла, КодировкаТекста.UTF8);
    Запись = Новый ЗаписьТекста(ИмяВременногоФайла, КодировкаТекста.UTF8);

    НомерТекущейСтроки = 0;
    
    // 2. В цикле читаем исходный файл и пишем во временный
    СтрокаФайла = Чтение.ПрочитатьСтроку();
    Пока СтрокаФайла <> Неопределено Цикл
        НомерТекущейСтроки = НомерТекущейСтроки + 1;
        
        Если НомерТекущейСтроки = НомерСтрокиДляЗамены Тогда
            // 3. Если нашли нужную строку, записываем новую
            Запись.ЗаписатьСтроку(НоваяСтрока);
        Иначе
            // 4. Иначе - записываем старую
            Запись.ЗаписатьСтроку(СтрокаФайла);
        КонецЕсли;
        
        СтрокаФайла = Чтение.ПрочитатьСтроку();
    КонецЦикла;

Исключение
    Сообщить("Ошибка при обработке файла: " + ОписаниеОшибки());
КонецПопытки;

// 5. Обязательно закрываем потоки, даже если была ошибка
Если Чтение <> Неопределено Тогда
    Чтение.Закрыть();
КонецЕсли;
Если Запись <> Неопределено Тогда
    Запись.Закрыть();
КонецЕсли;

// 6. Заменяем исходный файл временным (только если не было ошибок)
Если ОписаниеОшибки() = "" Тогда
    УдалитьФайлы(ИмяИсходногоФайла);
    ПереместитьФайл(ИмяВременногоФайла, ИмяИсходногоФайла);
    Сообщить("Файл успешно обновлен!");
КонецЕсли;

Этот код более сложный, но он является гораздо более надежным и масштабируемым решением для регулярной обработки файлов любого размера.

Сравнение подходов: что и когда использовать

Давайте подведем итог и определим, какой метод в каких случаях лучше применять.

1. `ТекстовыйДокумент`

2. `ЧтениеТекста` / `ЗаписьТекста`

3. Потоки (`ФайловыйПоток`)

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

Вывод: для задачи, описанной в начале (до 1000 строк в файле), использование ТекстовыйДокумент абсолютно оправдано. Главное — помнить о проверке данных перед записью. Однако для создания более универсального и масштабируемого решения лучше сразу ориентироваться на подход с построчной обработкой.

← На главную