При работе с внешними данными программисты 1С часто сталкиваются с необходимостью обработки текстовых файлов колоссальных объемов — 10, 15 и более гигабайт. В таких ситуациях возникают закономерные опасения по поводу стабильности системы и потребления оперативной памяти. Попытки реализовать алгоритм «прочитал — удалил — сохранил» часто приводят к ошибке «Метод объекта не обнаружен (УдалитьСтроку)». В этой статье мы подробно разберем, почему возникает эта ошибка, как на самом деле платформа 1С работает с памятью при чтении файлов и какие методы обработки являются наиболее эффективными.
Разберем ситуацию, представленную в коде автора темы. Для чтения данных используется объект ЧтениеТекста. Попытка вызвать метод УдалитьСтроку() у этого объекта всегда будет приводить к ошибке, так как этого метода просто не существует в программном интерфейсе (API) данного класса.
Проанализируем разницу между объектами, предназначенными для работы с текстом в 1С:
УдалитьСтроку(). Однако использование этого объекта для файлов объемом 15 ГБ категорически противопоказано. ТекстовыйДокумент при открытии файла пытается полностью загрузить его содержимое в оперативную память. В случае с файлом на 15 ГБ это приведет к немедленному падению сеанса 1С с ошибкой «Нехватка памяти».Таким образом, автор пытался применить метод от одного объекта (интерактивного редактора) к другому объекту (потоковому чтецу), что и вызвало технический сбой.
Основное заблуждение многих разработчиков заключается в том, что чтение файла объемом 15 ГБ «забьет» всю оперативную память сервера. Это не так. Выясним причину, почему последовательное чтение безопасно:
Объект ЧтениеТекста работает через механизм буферизации. Когда мы вызываем метод ПрочитатьСтроку(), платформа не загружает весь файл. Она считывает в оперативную память лишь небольшой фрагмент (буфер) размером в несколько мегабайт. Как только мы доходим до конца прочитанного блока, 1С автоматически подгружает следующий фрагмент, освобождая старый. Таким образом, даже при обработке терабайтного файла потребление памяти процессом rphost (или клиентским приложением) останется практически неизменным и очень низким.
Важный момент: Память может начать расти только в том случае, если вы сами внутри цикла будете записывать прочитанные строки в Массив, ТаблицуЗначений или Соответствие, которые хранятся в течение всего времени работы алгоритма. Если же вы прочитали строку, обработали её (например, создали документ в базе) и перешли к следующей, память очищается автоматически.
Рассмотрим физику процесса работы жесткого диска и файловой системы (NTFS или FAT32). Файл на диске — это последовательность байтов. Вы не можете просто «вырезать» первые 150 000 строк из файла без последствий. Чтобы удалить данные из начала, операционная система должна взять все оставшиеся 14,9 ГБ данных и физически перезаписать их, сдвигая в начало файла, чтобы закрыть образовавшуюся «дыру».
Если выполнять такую операцию циклично (прочитал порцию — перезаписал 15 ГБ), процесс растянется на недели, а ресурс дисковой подсистемы будет исчерпан крайне быстро из-за колоссальной нагрузки на ввод-вывод (I/O). Поэтому алгоритм «удаления прочитанного» для текстовых логов является самым медленным и ресурсоемким из всех возможных.
Проанализируем наиболее простой и эффективный способ обработки. Нам не нужно ничего удалять. Мы просто читаем файл от начала до конца за один проход.
Текст = Новый ЧтениеТекста;
Текст.Открыть(ПолноеИмяФайла, КодировкаТекста.UTF8);
Стр = Текст.ПрочитатьСтроку();
Пока Стр <> Неопределено Цикл
// Выполняем необходимую обработку данных строки
ОбработатьДанные(Стр);
// Переходим к следующей строке
Стр = Текст.ПрочитатьСтроку();
КонецЦикла;
Текст.Закрыть();
Этот код будет работать максимально быстро, потребляя минимум оперативной памяти, независимо от размера файла.
Если задача состоит в том, чтобы обрабатывать файл порциями (например, по 150 000 строк в рамках регламентного задания), и вы боитесь, что процесс прервется, используйте смещение (позицию) вместо удаления строк. Для этого в современной платформе 1С 8.3 используются объекты ФайловыйПоток и ЧтениеДанных.
Разберем алгоритм по шагам:
Перейти(), чтобы мгновенно переместиться к нужной точке, и продолжаем чтение.Пример кода для работы с позицией:
// Открываем поток для чтения
Поток = Новый ФайловыйПоток(ПолноеИмяФайла, РежимОткрытияФайла.Открыть, ДоступКФайлу.Чтение);
Чтение = Новый ЧтениеДанных(Поток);
// Если у нас сохранена позиция с прошлого раза
Если ЕстьСохраненнаяПозиция Тогда
Поток.Перейти(СохраненноеЗначениеПозиции, РежимПеремещенияВПотоке.Начало);
КонецЕсли;
Для Счетчик = 1 По 150000 Цикл
СтрокаДанных = Чтение.ПрочитатьСтроку();
Если СтрокаДанных = Неопределено Тогда
Прервать;
КонецЕсли;
Обработать(СтрокаДанных);
КонецЦикла;
// Сохраняем текущую позицию потока для следующего запуска
СохраненноеЗначениеПозиции = Поток.ТекущаяПозиция();
Чтение.Закрыть();
Если файл слишком велик для обработки одним потоком и вы хотите запустить несколько фоновых заданий параллельно, проанализируем вариант «разрезания» файла. Вместо того чтобы мучить 1С операциями удаления, воспользуйтесь системными утилитами. В Linux это команда split, в Windows можно использовать аналоги на PowerShell или сторонние бесплатные утилиты. Вы можете один раз разрезать 15-гигабайтный файл на 15 файлов по 1 ГБ и обрабатывать их независимо. Это значительно ускорит работу и упростит логику приложения.
Мы выяснили причину возникновения ошибки: объект ЧтениеТекста не поддерживает модификацию файла, он предназначен для эффективного потокового чтения. Для работы с огромными файлами в 1С следует придерживаться следующих правил:
ТекстовыйДокумент для файлов объемом более 100-200 МБ.ЧтениеТекста — буферизация платформы защищает систему от перегрузки.ФайловыйПоток и ЧтениеДанных, если вам нужен тонкий контроль над процессом чтения.