Чтение текстовых файлов во встроенном языке 1С 8.3: код, кодировки, большие объёмы

· 10 мин

Содержание

Прочитать TXT файл в 1С 8.3 проще всего объектом ЧтениеТекста: создаёте его с путём к файлу и кодировкой, затем вызываете ПрочитатьСтроку() в цикле, пока метод не вернёт Неопределено. Если файл небольшой и нужен целиком, хватит одной строки — Прочитать(). Для доступа к строке по номеру удобнее ТекстовыйДокумент.

Типичная ситуация: склад присылает выгрузку остатков из своей программы в виде текстового файла, и её надо разобрать в документ 1С. Ниже — рабочий код под каждый случай: маленький файл, файл на 500 МБ, «кракозябры» вместо кириллицы, файл на компьютере пользователя при работе через сервер. Всё сказанное относится к платформе 1С:Предприятие 8.3 и не зависит от конфигурации: БП, ЗУП, УТ — код одинаковый.

Чем открыть TXT в 1С: три объекта встроенного языка

У платформы есть три штатных способа прочитать текстовый файл. Они отличаются тем, сколько памяти тратят и что умеют.

ОбъектКак читаетКогда брать
ЧтениеТекстаПострочно или целиком, потокомПочти всегда; обязательно для больших файлов
ТекстовыйДокументЗагружает весь файл в памятьНужна строка по номеру, показать текст пользователю
ДвоичныеДанные + ПолучитьСтрокуИзДвоичныхДанных()Целиком из двоичных данныхФайл пришёл через временное хранилище или HTTP

Самый короткий вариант — прочитать весь текст одной командой:

Чтение = Новый ЧтениеТекста("C:\Обмен\ostatki.txt", КодировкаТекста.UTF8);
ВесьТекст = Чтение.Прочитать();
Чтение.Закрыть();

Метод Прочитать() без параметров возвращает содержимое файла одной строкой. Дальше её можно разбить на строки функцией СтрРазделить(ВесьТекст, Символы.ПС).

Тот же файл через ТекстовыйДокумент:

Текст = Новый ТекстовыйДокумент;
Текст.Прочитать("C:\Обмен\ostatki.txt", КодировкаТекста.UTF8);
Для НомерСтроки = 1 По Текст.КоличествоСтрок() Цикл
    Строка = Текст.ПолучитьСтроку(НомерСтроки);
    // обработка строки
КонецЦикла;

Нумерация строк в ТекстовыйДокумент начинается с 1, а не с 0. В массиве из СтрРазделить — с 0. Путаница здесь даёт потерю первой или последней строки.

ТекстовыйДокумент удобен ещё и тем, что его можно вывести на форму или открыть методом Показать() — пользователь увидит файл прямо в 1С.

Построчное чтение TXT файла: код, который выдержит гигабайт

Если файл крупный — журнал регистрации в текстовом виде, выгрузка из банка за год, прайс на 300 тысяч позиций, — не загружайте его целиком. Прочитать() и ТекстовыйДокумент держат весь текст в памяти, и на файлах в сотни мегабайт рабочий процесс или клиент упрётся в память.

Построчный вариант держит в памяти только текущую строку:

Процедура ПрочитатьФайлПострочно(ИмяФайла)

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

    Строка = Чтение.ПрочитатьСтроку();
    Пока Строка <> Неопределено Цикл
        НомерСтроки = НомерСтроки + 1;
        Если Не ПустаяСтрока(Строка) Тогда
            ОбработатьСтроку(Строка, НомерСтроки);
        КонецЕсли;
        Строка = Чтение.ПрочитатьСтроку();
    КонецЦикла;

    Чтение.Закрыть();

КонецПроцедуры

Ключевой момент — условие выхода. В конце файла ПрочитатьСтроку() возвращает Неопределено, а не пустую строку. Пустая строка "" — это нормальная пустая строка внутри файла, на ней цикл останавливать нельзя.

📌 Что ещё полезно знать про ЧтениеТекста:

  • 🔹 Пятый параметр конструктора — МонопольныйРежим. Если файл в этот момент пишет другая программа, передайте Ложь, иначе получите ошибку доступа.
  • 🔹 Разделитель строк по умолчанию — перевод строки; пары ВК+ПС из Windows-файлов обрабатываются корректно.
  • 🔹 Всегда вызывайте Закрыть(). Пока объект жив, файл может оставаться заблокированным для удаления или перезаписи.

Чтобы файл гарантированно закрывался даже при ошибке в обработке, оборачивайте цикл в Попытка … Исключение: в ветке исключения закройте чтение и вызовите ВызватьИсключение;, чтобы ошибка не потерялась.

Кодировки UTF-8, windows-1251, OEM и KOI8-R

«Кракозябры» после чтения — самая частая жалоба. Причина одна: файл записан в одной кодировке, а 1С читает его в другой. Кодировку передают вторым параметром — значением перечисления КодировкаТекста или строкой с именем кодировки.

Как выглядит файлЧто передать в 1С
Современная выгрузка, файл из веба, XML-подобные данныеКодировкаТекста.UTF8
Блокнот Windows старых версий, выгрузки старых программКодировкаТекста.ANSI или "windows-1251"
Вывод консольных программ, DOS-форматы, файлы 1С 7.7КодировкаТекста.OEM или "cp866"
Почтовые и Unix-системы с кириллицей"koi8-r"
Файл с BOM в UTF-16КодировкаТекста.UTF16

Пример с явной строковой кодировкой:

Чтение = Новый ЧтениеТекста(ИмяФайла, "koi8-r");

КодировкаТекста.ANSI означает кодировку Windows, заданную в системе. На русской Windows это windows-1251, но на сервере Linux или английской Windows результат может быть другим. Поэтому для выгрузок из чужих программ надёжнее писать имя кодировки строкой: "windows-1251".

Как понять кодировку, если её никто не назвал

  1. Откройте файл в Notepad++ или аналогичном редакторе — внизу окна видна определённая им кодировка.
  2. Если редактора нет, прочитайте первые строки поочерёдно в UTF-8 и в windows-1251 и выведите их через Сообщить(). Где кириллица читается — та и нужна.
  3. Посмотрите первые байты файла: EF BB BF в начале — это метка UTF-8 (BOM), FF FE — UTF-16.

Если в строке видно абв — файл в UTF-8, а читаете вы его как windows-1251. Если ���� или аЕЖ вместо «абв» — наоборот, однобайтовый файл открыт как UTF-8.

Невидимый символ BOM в начале первой строки — частый источник «необъяснимых» ошибок: первое поле не совпадает с ожидаемым заголовком, хотя на экране всё одинаково. При явном указании КодировкаТекста.UTF8 платформа его пропускает; если же вы получаете текст другим путём, уберите символ функцией СтрЗаменить(Строка, Символ(65279), "").

Файл на компьютере пользователя, а код выполняется на сервере

В клиент-серверной базе путь C:\Обмен\ostatki.txt в серверной процедуре ищется на диске сервера 1С, а не на ПК бухгалтера. Отсюда ошибка «файл не найден», хотя файл точно лежит на рабочем столе. То же в веб-клиенте и при работе в облаке.

Правильный порядок — передать файл на сервер через временное хранилище:

  1. На клиенте вызвать НачатьПомещениеФайла() — пользователь выбирает файл в диалоге.
  2. Файл попадает во временное хранилище, клиент получает его адрес.
  3. На сервере достать двоичные данные и прочитать их как текст.
&НаКлиенте
Процедура ЗагрузитьФайл(Команда)
    Оповещение = Новый ОписаниеОповещения("ПослеПомещенияФайла", ЭтотОбъект);
    НачатьПомещениеФайла(Оповещение, , , Истина, УникальныйИдентификатор);
КонецПроцедуры

&НаКлиенте
Процедура ПослеПомещенияФайла(Результат, Адрес, ВыбранноеИмяФайла, ДополнительныеПараметры) Экспорт
    Если Результат Тогда
        ПрочитатьНаСервере(Адрес);
    КонецЕсли;
КонецПроцедуры

&НаСервере
Процедура ПрочитатьНаСервере(Адрес)
    Данные = ПолучитьИзВременногоХранилища(Адрес);
    ИмяВременногоФайла = ПолучитьИмяВременногоФайла("txt");
    Данные.Записать(ИмяВременногоФайла);

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

    УдалитьФайлы(ИмяВременногоФайла);
КонецПроцедуры

Для небольшого файла временный файл не нужен: ПолучитьСтрокуИзДвоичныхДанных(Данные, КодировкаТекста.UTF8) сразу вернёт текст. Для больших объёмов вариант с временным файлом и построчным чтением экономнее.

Если файл регулярно кладут в общую сетевую папку, укажите в коде UNC-путь вида \\fileserver\obmen\ostatki.txt. Учётная запись, под которой работает служба сервера 1С, должна иметь права на чтение этой папки — иначе файл «не найдётся», хотя из проводника пользователя он открывается.

COM-объекты и внешние компоненты: когда штатного мало

На Windows можно читать файлы через COM. Это нужно редко — штатные объекты справляются почти со всем, — но пригодится в двух случаях: код достался по наследству со времён 8.2 или нужна кодировка/функция, которой нет в платформе.

Scripting.FileSystemObject — построчное чтение однобайтовых файлов:

ФСО = Новый COMОбъект("Scripting.FileSystemObject");
Файл = ФСО.OpenTextFile("C:\Обмен\ostatki.txt", 1); // 1 — только чтение
Пока Не Файл.AtEndOfStream Цикл
    Строка = Файл.ReadLine();
    // обработка
КонецЦикла;
Файл.Close();

ADODB.Stream — понимает UTF-8 и другие кодировки через свойство Charset:

Поток = Новый COMОбъект("ADODB.Stream");
Поток.Type = 2; // текстовый режим
Поток.Charset = "utf-8";
Поток.Open();
Поток.LoadFromFile("C:\Обмен\ostatki.txt");
Текст = Поток.ReadText();
Поток.Close();

Ограничения COM:

  • ❌ не работает на сервере 1С под Linux и в веб-клиенте;
  • ❌ в серверном коде объект создаётся на сервере, под учётной записью службы 1С;
  • ❌ в безопасном режиме и при включённых профилях безопасности создание COM-объектов запрещено.

Внешние компоненты (технология Native API) подключают, когда нужен особый формат: нестандартное сжатие, фиксированные бинарные заголовки внутри текста, очень быстрый разбор многогигабайтных логов. Готовую компоненту получают от разработчика вместе с макетом и подключают методами ПодключитьВнешнююКомпоненту() или асинхронными аналогами. Писать свою ради обычного TXT не имеет смысла.

Если же текст лежит не на диске, а на сайте или в API, его не нужно сохранять вручную: HTTPСоединение получает ответ, а HTTPОтвет.ПолучитьТелоКакСтроку("UTF-8") сразу даёт строку для разбора.

Разбор строк: разделители, фиксированная ширина, числа и даты

Прочитать строку — полдела. Дальше её нужно разложить на поля. Возьмём файл с разделителем «;»:

Артикул;Наименование;Количество;Цена
A-1001;Бумага А4;25;389,50
A-1002;Скрепки 28 мм;100;42

Разбор с пропуском заголовка и накоплением в таблицу значений:

Таблица = Новый ТаблицаЗначений;
Таблица.Колонки.Добавить("Артикул", Новый ОписаниеТипов("Строка"));
Таблица.Колонки.Добавить("Наименование", Новый ОписаниеТипов("Строка"));
Таблица.Колонки.Добавить("Количество", Новый ОписаниеТипов("Число"));
Таблица.Колонки.Добавить("Цена", Новый ОписаниеТипов("Число"));

ТипЧисло = Новый ОписаниеТипов("Число");
Чтение = Новый ЧтениеТекста(ИмяФайла, "windows-1251");
Строка = Чтение.ПрочитатьСтроку(); // заголовок пропускаем
Строка = Чтение.ПрочитатьСтроку();
Пока Строка <> Неопределено Цикл
    Поля = СтрРазделить(Строка, ";", Истина);
    Если Поля.Количество() >= 4 Тогда
        НоваяСтрока = Таблица.Добавить();
        НоваяСтрока.Артикул = СокрЛП(Поля[0]);
        НоваяСтрока.Наименование = СокрЛП(Поля[1]);
        НоваяСтрока.Количество = ТипЧисло.ПривестиЗначение(СтрЗаменить(СокрЛП(Поля[2]), ",", "."));
        НоваяСтрока.Цена = ТипЧисло.ПривестиЗначение(СтрЗаменить(СокрЛП(Поля[3]), ",", "."));
    КонецЕсли;
    Строка = Чтение.ПрочитатьСтроку();
КонецЦикла;
Чтение.Закрыть();

Третий параметр СтрРазделить — Истина — сохраняет пустые поля. С Ложь строка A-1003;;5;10 превратится в три элемента вместо четырёх, и колонки «съедут». ПривестиЗначение для числа не падает на мусоре — вернёт 0. Если пустое значение нужно отличать от нуля, проверяйте исходную строку отдельно.

Файл с фиксированной шириной полей (банковские и старые учётные выгрузки) разбирают функцией Сред():

Артикул = СокрЛП(Сред(Строка, 1, 10));   // позиции 1–10
Наименование = СокрЛП(Сред(Строка, 11, 40)); // позиции 11–50
Сумма = СокрЛП(Сред(Строка, 51, 12));      // позиции 51–62

Формат «Ключ=Значение» — как в файле обмена с банком 1CClientBankExchange — разбирается по первому знаку равенства:

Позиция = СтрНайти(Строка, "=");
Если Позиция > 0 Тогда
    Ключ = Лев(Строка, Позиция - 1);
    Значение = Сред(Строка, Позиция + 1);
КонецЕсли;

Даты в виде 15.03.2025 переводят в тип «Дата» сборкой строки ГГГГММДД: Дата(Прав(Ст, 4) + Сред(Ст, 4, 2) + Лев(Ст, 2)). Оберните это в Попытка, если файл заполняли вручную.

Скорость обработки больших файлов

Чтение само по себе быстрое. Тормозит обычно то, что делается со строкой после. Вот что реально ускоряет загрузку:

  • ⚡ Не используйте СтрПолучитьСтроку() в цикле по всему тексту. Каждый вызов заново ищет строку с начала, и время растёт квадратично. На 100 тысячах строк это минуты вместо секунд. Берите ПрочитатьСтроку() или массив из СтрРазделить.
  • ⚡ Не ищите элементы справочника запросом на каждую строку. Сначала соберите все артикулы в таблицу, одним запросом получите ссылки, затем сопоставьте через Соответствие.
  • ⚡ Записывайте пачками. Объекты пишите в транзакциях по 500–1000 штук, а не одной транзакцией на весь файл: длинная транзакция держит блокировки и при ошибке откатывает всё.
  • ⚡ Не склеивайте большую строку в цикле через Текст = Текст + Строка. Для накопления используйте массив и СтрСоединить() или объект ЗаписьТекста.
  • ⚡ Уводите загрузку в фон. Обработку на десятки минут запускайте фоновым заданием — интерфейс не зависнет, а прогресс в типовых конфигурациях показывают через механизм длительных операций БСП.

Перед первой загрузкой в рабочую базу прогоните обработку на копии. Ошибка в разборе колонок на 50 тысячах строк создаёт столько же испорченных документов.

Перед запуском загрузки из TXT
Выполнено: 0 / 7

Ошибки при чтении TXT и как их исправить

Диагностика: выберите симптом

Если ни один вариант не подошёл, проверьте права на файл от имени той учётной записи, под которой реально выполняется код. Для серверного кода это пользователь службы 1С, а не тот, кто сидит за компьютером.

Частые вопросы

Можно ли прочитать TXT без программирования?
Да, если нужен просмотр: команда меню Файл → Открыть в клиенте 1С откроет текстовый файл в окне программы. Для загрузки данных в документы и справочники без кода не обойтись — нужна внешняя обработка.
Где запустить код чтения, если нет конфигуратора?
Создайте внешнюю обработку в конфигураторе любой базы, сохраните её как файл .epf и откройте в рабочей базе через Файл → Открыть. Для открытия нужны права на внешние обработки.
Чем ЧтениеТекста отличается от ЧтениеДанных?
ЧтениеТекста работает с текстом и кодировками. ЧтениеДанных читает байты и нужен для двоичных форматов или когда текст перемешан с двоичными блоками.
Как прочитать файл, который лежит внутри ZIP-архива?
Распакуйте архив объектом ЧтениеZipФайла во временный каталог, затем читайте извлечённый TXT обычным ЧтениеТекста и удалите временные файлы.
Как записать результат обратно в TXT?
Объектом ЗаписьТекста с той же кодировкой: метод ЗаписатьСтроку добавляет строку, Закрыть сохраняет файл.