Как обработать текстовый файл с фиксированным количеством строк в блоке данных?

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

В практике интеграции 1С с внешними системами часто встречаются ситуации, когда данные передаются в «плоских» текстовых файлах. Одной из специфических задач является обработка файлов, где информация о конкретном объекте (например, о поставке товара) занимает строго определенное количество строк. Рассмотрим ситуацию, когда каждые 10 строк файла содержат набор связанных данных: контрагент, организация, дата, товар и так далее, после чего цикл повторяется для следующей поставки.

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

Метод 1: Использование счетчика и остатка от деления

Этот способ является классическим и наиболее понятным для тех, кто привык обходить файлы построчно в едином цикле. Суть заключается в том, чтобы отслеживать номер текущей строки и определять ее позицию внутри блока из 10 строк.

Разберем, как это работает программно. Мы можем использовать оператор % (остаток от деления) или простой инкрементный счетчик, который сбрасывается при достижении нужного значения. Проанализируем пример кода с использованием счетчика:


Счетчик = 0;
Чтение = Новый ЧтениеТекста(ИмяФайла, КодировкаТекста.UTF8);
Стр = Чтение.ПрочитатьСтроку();

Пока Стр <> Неопределено Цикл
    Счетчик = Счетчик + 1;
    
    // Определяем, какая именно это строка в блоке
    Если Счетчик = 1 Тогда
        ТекущийКонтрагент = Стр;
    ИначеЕсли Счетчик = 2 Тогда
        ТекущаяОрганизация = Стр;
    ИначеЕсли Счетчик = 3 Тогда
        ТекущаяДата = Стр;
    // ... и так далее до 10
    КонецЕсли;

    Если Счетчик = 10 Тогда
        // Блок данных полностью собран, создаем документ
        СоздатьДокументПоставки(ТекущийКонтрагент, ТекущаяОрганизация, ТекущаяДата);
        // Сбрасываем счетчик для следующего блока
        Счетчик = 0;
    КонецЕсли;

    Стр = Чтение.ПрочитатьСтроку();
КонецЦикла;

Преимущества: простота реализации и возможность легко «пропустить» ненужные строки внутри блока. Недостатки: код становится громоздким при большом количестве строк в блоке из-за множественных условий ИначеЕсли.

Метод 2: Последовательное чтение внутри основного цикла

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

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


Чтение = Новый ЧтениеТекста(ИмяФайла, КодировкаТекста.UTF8);
Пока Истина Цикл
    // Читаем первую строку блока
    Контрагент = Чтение.ПрочитатьСтроку();
    Если Контрагент = Неопределено Тогда Прервать; КонецЕсли;

    // Читаем остальные строки блока последовательно
    Организация = Чтение.ПрочитатьСтроку();
    ДатаСтр = Чтение.ПрочитатьСтроку();
    Товар = Чтение.ПрочитатьСтроку();
    // Пропускаем оставшиеся строки до 10, если они не нужны
    Для н = 1 По 6 Цикл
        Чтение.ПрочитатьСтроку();
    КонецЦикла;

    // Выполняем обработку собранного блока
    ОбработатьДанныеПоставки(Контрагент, Организация, ДатаСтр, Товар);
КонецЦикла;
Чтение.Закрыть();

Этот метод значительно чище с точки зрения архитектуры кода. Мы точно знаем, какая переменная за что отвечает, и не загромождаем алгоритм проверками номера строки на каждой итерации.

Валидация данных и защита от «смещения» строк

Одной из главных проблем при обработке файлов с фиксированной структурой строк является риск их смещения. Если поставщик случайно добавит лишнюю строку или удалит одну из пустых строк, весь алгоритм «поедет», и в поле «Контрагент» может попасть «Наименование товара».

Чтобы минимизировать риски, выясним причины возможных сбоев и внедрим контрольные точки:

  1. Проверка формата данных: Если мы знаем, что в третьей строке всегда должна быть дата, необходимо проверить ее на соответствие типу. Используйте попытку приведения или регулярные выражения.
  2. Контрольные значения: Если в структуре файла есть строки с фиксированными заголовками или специфическими префиксами, обязательно проверяйте их наличие.
  3. Очистка строк: Перед преобразованием строки в число или дату используйте СокрЛП() и удаляйте неразрывные пробелы с помощью СтрЗаменить(Стр, Символы.НПП, "").

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


Функция ПреобразоватьДатуИзФайла(Знач СтрДата)
    // Допустим, формат в файле ДД.ММ.ГГГГ
    Попытка
        День = Число(Лев(СтрДата, 2));
        Месяц = Число(Сред(СтрДата, 4, 2));
        Год = Число(Сред(СтрДата, 7, 4));
        Возврат Дата(Год, Месяц, День);
    Исключение
        Возврат Дата(1, 1, 1);
    КонецПопытки;
КонецФункции

Работа с большими файлами и Web-сервисами

Если загрузка выполняется через Web-сервис, важно помнить о таймаутах соединения. Обработка файла из 100 000 строк может занять значительное время. В таких случаях рекомендуем рассмотреть следующую схему:

  1. Web-сервис принимает файл и сохраняет его во временное хранилище или в специальный справочник.
  2. Сразу после получения файла сервис запускает ФоновоеЗадание для его обработки.
  3. Пользователь или внешняя система получает идентификатор задания и может опрашивать статус завершения загрузки.

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

Резюме

Мы рассмотрели два основных подхода к обработке структурированных текстовых файлов. Использование счетчика с оператором остатка от деления (% 10) удобно для простых задач, однако последовательное чтение строк внутри цикла является более профессиональным и читаемым решением. Главное при реализации подобных алгоритмов — уделять внимание валидации входящих строк, чтобы исключить попадание некорректных данных в информационную базу при случайном изменении структуры файла поставщиком.

← На главную