Как убрать лишние переносы строк в файле выгрузки из клиент-банка при загрузке в 1С

Программист 1С v8.3 (Управляемые формы) Бухгалтерский учет Финансы и профессиональные услуги
← На главную

При интеграции 1С с банковскими системами программисты часто сталкиваются с ситуацией, когда файл выгрузки, визуально выглядящий корректно в обычном блокноте, «разваливается» при попытке прочитать его программно. Проблема заключается в скрытых символах переноса строки, которые нарушают логическую структуру данных. В этой статье мы подробно разберем, почему это происходит, как диагностировать проблему и какими программными способами можно очистить файл перед загрузкой.

Анализ ситуации: почему возникают лишние переносы

В операционной системе Windows стандартом окончания строки является пара символов CRLF (возврат каретки — CR, код 13, и перевод строки — LF, код 10). Однако многие банковские сервера работают под управлением Unix-подобных систем, где разделителем является только одиночный символ LF.

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

Диагностика проблемы с помощью внешних инструментов

Прежде чем приступать к написанию кода, нам необходимо точно выяснить, какой именно символ мешает загрузке. Проанализируем файл с помощью текстового редактора Notepad++:

  1. Откроем файл выгрузки в Notepad++.
  2. На панели инструментов нажмем кнопку «Отображать все символы» (выглядит как знак параграфа ).
  3. Посмотрим на проблемные участки текста. Если в конце нормальной строки вы видите [CR][LF], а в середине данных — только [LF], значит, мы нашли причину сбоя.
  4. Дополнительно проверим кодировку в меню «Кодировки» (обычно это ANSI или UTF-8).

Решение №1: Метод «Маркера» для очистки текста

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

Рассмотрим пример кода:


// Считываем весь файл в строку
ТекстДокумента = ПолучитьТекстИзФайла(ПутьКФайлу);

// 1. Заменяем правильные переносы строк на уникальный маркер, который точно не встретится в тексте
Маркер = "###МАРКЕР_СТРОКИ###";
ТекстДокумента = СтрЗаменить(ТекстДокумента, Символы.ВК + Символы.ПС, Маркер);

// 2. Теперь удаляем все оставшиеся одиночные символы переноса
ТекстДокумента = СтрЗаменить(ТекстДокумента, Символы.ПС, " "); // Заменяем LF на пробел
ТекстДокумента = СтрЗаменить(ТекстДокумента, Символы.ВК, " "); // Заменяем CR на пробел (на всякий случай)

// 3. Возвращаем правильные переносы строк обратно
ТекстДокумента = СтрЗаменить(ТекстДокумента, Маркер, Символы.ВК + Символы.ПС);

Этот метод гарантирует, что структура файла сохранится, а лишние разрывы внутри полей (например, в адресе Вася Г. МИНСК) превратятся в обычные пробелы.

Решение №2: Использование функции СтрРазделить по логическому разделителю

Если в вашем файле данные разделены специальным символом (в нашем случае автор указал символ $), мы можем использовать более современный подход. Функция СтрРазделить позволяет игнорировать физические переносы строк, если мы точно знаем структуру документа.

Разберем по шагам, как это реализовать:


// Читаем весь текст файла
ЧтениеТекста = Новый ЧтениеТекста(ПутьКФайлу, КодировкаТекста.ANSI);
ПолныйТекст = ЧтениеТекста.Прочитать();
ЧтениеТекста.Закрыть();

// Разделяем текст в массив по символу "$"
МассивДанных = СтрРазделить(ПолныйТекст, "$", Истина);

// Теперь в МассивДанных[2] может содержаться текст с переносом "ИП Вася\nМИНСК",
// но он не разрывает логику обработки остальных полей.
// При необходимости внутри каждого элемента массива можно удалить ПС:
Для Каждого Элемент Из МассивДанных Цикл
    ОчищенноеЗначение = СтрЗаменить(Элемент, Символы.ПС, " ");
    // Далее работаем с очищенными данными
КонецЦикла;

Решение №3: Работа с файлом как с двоичными данными

В ситуациях, когда файл очень большой (десятки или сотни мегабайт), загрузка его целиком в память в виде строки может вызвать ошибку Нехватка памяти. В таких случаях проанализируем файл как поток байтов. Нам нужно найти байт с кодом 10 (LF) и проверить, стоит ли перед ним байт 13 (CR).

Посмотрим на пример реализации:


ДвоичныеДанные = Новый ДвоичныеДанные(ПутьКФайлу);
ЧтениеДанных = Новый ЧтениеДанных(ДвоичныеДанные);
Буфер = ЧтениеДанных.Прочитать(); // Читаем всё или порциями
ЧтениеДанных.Закрыть();

НовыйБуфер = Новый Массив;
ПредыдущийБайт = 0;

Для Каждого ТекущийБайт Из Буфер Цикл
    Если ТекущийБайт = 10 Тогда // Это LF
        Если ПредыдущийБайт <> 13 Тогда // Перед ним нет CR
            // Это "плохой" перенос. Заменим его на байт пробела (код 32)
            НовыйБуфер.Добавить(32);
        Иначе
            НовыйБуфер.Добавить(ТекущийБайт);
        КонецЕсли;
    Иначе
        НовыйБуфер.Добавить(ТекущийБайт);
    КонецЕсли;
    ПредыдущийБайт = ТекущийБайт;
КонецЦикла;

// Сохраняем очищенный файл
РезультатДанные = Новый ДвоичныеДанные(НовыйБуфер);
РезультатДанные.Записать(ПутьКФайлуОчищенный);

Рекомендации по автоматизации процесса

Чтобы каждый раз не править код при изменении формата банка, рекомендуется реализовать механизм предварительной «нормализации» файла. Создайте отдельную функцию НормализоватьФайлЗагрузки(), которая будет вызываться перед основным алгоритмом обработки.

Важные моменты:

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

← На главную