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