В практике интеграции 1С с внешними системами часто встречаются ситуации, когда данные передаются в «плоских» текстовых файлах. Одной из специфических задач является обработка файлов, где информация о конкретном объекте (например, о поставке товара) занимает строго определенное количество строк. Рассмотрим ситуацию, когда каждые 10 строк файла содержат набор связанных данных: контрагент, организация, дата, товар и так далее, после чего цикл повторяется для следующей поставки.
В данной статье мы разберем несколько подходов к решению этой задачи, проанализируем их преимущества и недостатки, а также обсудим вопросы надежности и производительности алгоритмов.
Этот способ является классическим и наиболее понятным для тех, кто привык обходить файлы построчно в едином цикле. Суть заключается в том, чтобы отслеживать номер текущей строки и определять ее позицию внутри блока из 10 строк.
Разберем, как это работает программно. Мы можем использовать оператор % (остаток от деления) или простой инкрементный счетчик, который сбрасывается при достижении нужного значения. Проанализируем пример кода с использованием счетчика:
Счетчик = 0;
Чтение = Новый ЧтениеТекста(ИмяФайла, КодировкаТекста.UTF8);
Стр = Чтение.ПрочитатьСтроку();
Пока Стр <> Неопределено Цикл
Счетчик = Счетчик + 1;
// Определяем, какая именно это строка в блоке
Если Счетчик = 1 Тогда
ТекущийКонтрагент = Стр;
ИначеЕсли Счетчик = 2 Тогда
ТекущаяОрганизация = Стр;
ИначеЕсли Счетчик = 3 Тогда
ТекущаяДата = Стр;
// ... и так далее до 10
КонецЕсли;
Если Счетчик = 10 Тогда
// Блок данных полностью собран, создаем документ
СоздатьДокументПоставки(ТекущийКонтрагент, ТекущаяОрганизация, ТекущаяДата);
// Сбрасываем счетчик для следующего блока
Счетчик = 0;
КонецЕсли;
Стр = Чтение.ПрочитатьСтроку();
КонецЦикла;
Преимущества: простота реализации и возможность легко «пропустить» ненужные строки внутри блока. Недостатки: код становится громоздким при большом количестве строк в блоке из-за множественных условий ИначеЕсли.
Более элегантный и производительный подход заключается в том, чтобы внутри основного цикла Пока вызывать метод ПрочитатьСтроку() столько раз, сколько строк содержится в одном информационном блоке. Это позволяет сразу присваивать значения нужным переменным без использования дополнительных условий и счетчиков.
Рассмотрим реализацию этого метода. Обратите внимание, что при таком подходе крайне важно проверять результат каждого чтения на Неопределено, чтобы избежать ошибок, если файл обрывается неожиданно.
Чтение = Новый ЧтениеТекста(ИмяФайла, КодировкаТекста.UTF8);
Пока Истина Цикл
// Читаем первую строку блока
Контрагент = Чтение.ПрочитатьСтроку();
Если Контрагент = Неопределено Тогда Прервать; КонецЕсли;
// Читаем остальные строки блока последовательно
Организация = Чтение.ПрочитатьСтроку();
ДатаСтр = Чтение.ПрочитатьСтроку();
Товар = Чтение.ПрочитатьСтроку();
// Пропускаем оставшиеся строки до 10, если они не нужны
Для н = 1 По 6 Цикл
Чтение.ПрочитатьСтроку();
КонецЦикла;
// Выполняем обработку собранного блока
ОбработатьДанныеПоставки(Контрагент, Организация, ДатаСтр, Товар);
КонецЦикла;
Чтение.Закрыть();
Этот метод значительно чище с точки зрения архитектуры кода. Мы точно знаем, какая переменная за что отвечает, и не загромождаем алгоритм проверками номера строки на каждой итерации.
Одной из главных проблем при обработке файлов с фиксированной структурой строк является риск их смещения. Если поставщик случайно добавит лишнюю строку или удалит одну из пустых строк, весь алгоритм «поедет», и в поле «Контрагент» может попасть «Наименование товара».
Чтобы минимизировать риски, выясним причины возможных сбоев и внедрим контрольные точки:
СокрЛП() и удаляйте неразрывные пробелы с помощью СтрЗаменить(Стр, Символы.НПП, "").Проанализируем пример функции для безопасного преобразования даты, так как стандартные методы могут вызывать исключения при некорректном формате из файла:
Функция ПреобразоватьДатуИзФайла(Знач СтрДата)
// Допустим, формат в файле ДД.ММ.ГГГГ
Попытка
День = Число(Лев(СтрДата, 2));
Месяц = Число(Сред(СтрДата, 4, 2));
Год = Число(Сред(СтрДата, 7, 4));
Возврат Дата(Год, Месяц, День);
Исключение
Возврат Дата(1, 1, 1);
КонецПопытки;
КонецФункции
Если загрузка выполняется через Web-сервис, важно помнить о таймаутах соединения. Обработка файла из 100 000 строк может занять значительное время. В таких случаях рекомендуем рассмотреть следующую схему:
Для повышения производительности при чтении очень больших файлов на современных платформах (8.3.10+) вместо ЧтениеТекста можно использовать объект ЧтениеДанных. Он позволяет более гибко работать с потоками, особенно если данные приходят в бинарном виде.
Мы рассмотрели два основных подхода к обработке структурированных текстовых файлов. Использование счетчика с оператором остатка от деления (% 10) удобно для простых задач, однако последовательное чтение строк внутри цикла является более профессиональным и читаемым решением. Главное при реализации подобных алгоритмов — уделять внимание валидации входящих строк, чтобы исключить попадание некорректных данных в информационную базу при случайном изменении структуры файла поставщиком.