В процессе разработки часто возникает задача изменить содержимое текстового файла, например, обновить конфигурационный параметр или заменить строку с данными. На первый взгляд, это простая операция, но иногда она приводит к неожиданным результатам, таким как дублирование всего содержимого файла вместо замены одной строки.
В этой статье мы разберем, как корректно выполнять замену строки в текстовом файле в 1С. Проанализируем стандартный подход с использованием объекта ТекстовыйДокумент, выясним, почему он может работать не так, как ожидалось, и рассмотрим более производительные альтернативы для работы с большими файлами.
Для работы с небольшими текстовыми файлами (до нескольких тысяч строк или нескольких мегабайт) самым простым и удобным является объект ТекстовыйДокумент. Он полностью загружает файл в оперативную память, что позволяет легко манипулировать его содержимым с помощью встроенных методов.
Стандартный алгоритм замены строки выглядит следующим образом:
ТекстовыйДокумент.Прочитать().ЗаменитьСтроку(<НомерСтроки>, <ТекстНовойСтроки>).Записать(), который полностью перезаписывает исходный файл.Посмотрим на пример кода, который решает эту задачу:
// Путь к файлу
запФайл = "C:\Temp\mydata.txt";
// Номер строки для замены (нумерация с 1)
стрЗап = 15;
// Новая строка, которую нужно записать (например, в формате JSON)
строкЖС = "{""id"": 123, ""value"": ""Новые данные""}";
// Создаем и читаем документ
ЗаписьДанных = Новый ТекстовыйДокумент;
ЗаписьДанных.Прочитать(запФайл, КодировкаТекста.UTF8);
// Заменяем строку
ЗаписьДанных.ЗаменитьСтроку(стрЗап, строкЖС);
// Перезаписываем весь файл
ЗаписьДанных.Записать(запФайл, КодировкаТекста.UTF8);
Сообщить("Строка " + стрЗап + " в файле " + запФайл + " успешно заменена!");
В ситуации, описанной на форуме, автор столкнулся с тем, что вместо замены строки содержимое файла дублировалось в его конец. Что могло стать причиной? Код, представленный выше, является корректным. Метод Записать() всегда перезаписывает файл целиком.
Проблема почти всегда кроется не в методах 1С, а в данных, которые мы пытаемся записать. Наиболее вероятная причина такого поведения — некорректно сформированная заменяющая строка (в нашем примере — переменная строкЖС).
Что нужно проверить:
Символы.ПС). Если они есть, это может нарушить структуру документа.ЗаменитьСтроку() выведите содержимое переменной с новой строкой в окно сообщений или отладчик. Возможно, в процессе ее формирования в нее ошибочно попадает все содержимое исходного файла.КодировкаТекста.UTF8), чтобы избежать проблем с отображением символов.Таким образом, если вы столкнулись с аномальным поведением при записи, в первую очередь тщательно проверьте данные, которые вы записываете.
Метод с ТекстовыйДокумент удобен, но неэффективен для больших файлов, так как требует загрузки всего содержимого в оперативную память. Если вы работаете с файлами размером в десятки или сотни мегабайт, это может вызвать замедление работы системы или даже ошибку нехватки памяти.
Для таких случаев существует более производительный подход — последовательная построчная обработка с использованием объектов ЧтениеТекста и ЗаписьТекста. Этот метод не имеет прямого аналога ЗаменитьСтроку(), поэтому логику придется реализовать самостоятельно.
Алгоритм построчной замены:
ЧтениеТекста.ЗаписьТекста.Этот подход потребляет минимум оперативной памяти, так как в каждый момент времени в ней находится только одна строка.
Рассмотрим пример реализации этого алгоритма:
// Исходные данные
ИмяИсходногоФайла = "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 строк в файле), использование ТекстовыйДокумент абсолютно оправдано. Главное — помнить о проверке данных перед записью. Однако для создания более универсального и масштабируемого решения лучше сразу ориентироваться на подход с построчной обработкой.