Чтение файлов с диска во встроенном языке 1С 8.3

· 10 мин

Содержание

Чтобы прочитать файл в 1С, для текста (txt, csv, log) берут объект ЧтениеТекста и читают построчно методом ПрочитатьСтроку(). Для XML — ЧтениеXML или ПостроительDOM. Для любых других форматов — ДвоичныеДанные и потоки (ФайловыйПоток, ЧтениеДанных). Способ выбирают по размеру и формату: маленький txt можно загрузить целиком, файл на сотни мегабайт читают только потоком.

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

Как прочитать текстовый файл в 1С построчно и целиком

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

ОбъектКак читаетКогда брать
ЧтениеТекстапострочно, потокомфайлы любого размера, логи, выгрузки
ТекстовыйДокументзагружает файл в память целикомнебольшие файлы, нужен доступ к строке по номеру

Построчное чтение через ЧтениеТекста

Это основной способ. В памяти держится одна строка, поэтому файл на 500 МБ читается так же спокойно, как на 5 КБ.

ИмяФайла = "C:\Обмен\prices.txt";
Чтение = Новый ЧтениеТекста(ИмяФайла, КодировкаТекста.UTF8);
Строка = Чтение.ПрочитатьСтроку();
Пока Строка <> Неопределено Цикл
	// обработка строки
	Сообщить(Строка);
	Строка = Чтение.ПрочитатьСтроку();
КонецЦикла;
Чтение.Закрыть();

Как работает цикл:

  1. Конструктор открывает файл в указанной кодировке.
  2. ПрочитатьСтроку() возвращает очередную строку без символа перевода.
  3. Когда строки кончились, метод возвращает Неопределено — это и есть признак конца файла.
  4. Закрыть() освобождает файл. Без него другой процесс не сможет его удалить или перезаписать.

Пустая строка в файле приходит как "", а не как Неопределено. Поэтому проверка Пока Строка <> "" оборвёт чтение на первой пустой строке. Сравнивайте именно с Неопределено.

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

Загрузка целиком через ТекстовыйДокумент

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

Нумерация строк здесь начинается с единицы. Плюс подхода — можно сразу узнать число строк и показать прогресс. Минус — весь файл лежит в памяти, а на клиенте синхронный Прочитать может блокировать интерфейс. В клиентском коде под веб-клиент используют асинхронные варианты.

Разбор CSV и табличных файлов в 1С

Отдельного встроенного объекта для CSV в платформе нет. CSV — это текст, поэтому его читают через ЧтениеТекста, а каждую строку делят на поля.

Простой случай: поля без кавычек

Если в значениях нет разделителя и кавычек, хватает функции СтрРазделить:

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

Третий параметр Истина у СтрРазделить сохраняет пустые поля. Без него строка А;;100 даст два элемента вместо трёх, и колонки съедут.

Поля в кавычках

Excel и большинство выгрузок берут значение в кавычки, если внутри есть разделитель: "ООО ""Ромашка""; склад";150. СтрРазделить такую строку разрежет неправильно. Нужен разбор посимвольно:

Функция РазобратьСтрокуCSV(Строка, Разделитель = ";")
	Поля = Новый Массив;
	Поле = "";
	ВКавычках = Ложь;
	Длина = СтрДлина(Строка);
	Сч = 1;
	Пока Сч <= Длина Цикл
		Символ = Сред(Строка, Сч, 1);
		Если ВКавычках Тогда
			Если Символ = """" Тогда
				Если Сред(Строка, Сч + 1, 1) = """" Тогда
					Поле = Поле + """"; // удвоенная кавычка внутри значения
					Сч = Сч + 1;
				Иначе
					ВКавычках = Ложь;
				КонецЕсли;
			Иначе
				Поле = Поле + Символ;
			КонецЕсли;
		ИначеЕсли Символ = """" Тогда
			ВКавычках = Истина;
		ИначеЕсли Символ = Разделитель Тогда
			Поля.Добавить(Поле);
			Поле = "";
		Иначе
			Поле = Поле + Символ;
		КонецЕсли;
		Сч = Сч + 1;
	КонецЦикла;
	Поля.Добавить(Поле);
	Возврат Поля;
КонецФункции

Для строки из примера функция вернёт два поля: ООО "Ромашка"; склад и 150. Ограничение одно: перенос строки внутри кавычек она не склеит. Если такие значения встречаются, накапливайте строку, пока число кавычек в ней нечётное.

Числа и даты из CSV

Числа в выгрузках приходят с запятой и пробелами-разделителями тысяч: 1 250,50. Функция Число() такую строку не примет. Чистим вручную:

Функция ЧислоИзСтроки(Знач Значение)
	Значение = СтрЗаменить(Значение, " ", "");
	Значение = СтрЗаменить(Значение, Символы.НПП, "");
	Значение = СтрЗаменить(Значение, ",", ".");
	Если Значение = "" Тогда
		Возврат 0;
	КонецЕсли;
	Попытка
		Возврат Число(Значение);
	Исключение
		Возврат 0;
	КонецПопытки;
КонецФункции

Дату вида 07.10.2026 собирают из частей: Дата(Число(Сред(Стр, 7, 4)), Число(Сред(Стр, 4, 2)), Число(Сред(Стр, 1, 2))). Для строки 07.10.2026 получится 7 октября 2026 года.

Если файл в формате xlsx

Когда вместо CSV прислали книгу Excel, переводить её в текст не обязательно. Объект ТабличныйДокумент читает xlsx и ods методом Прочитать, после чего значения берут из ячеек через ПолучитьОбласть или Область("R2C1").Текст. Файл читают на сервере, куда его заранее передали.

Чтение и разбор XML в 1С

Для XML у платформы три уровня. Выбор зависит от размера файла и от того, нужна ли схема.

СпособПамятьУдобствоКогда подходит
ЧтениеXMLминимум, потоковое чтениениже, идём по узлам вручнуюбольшие файлы, выгрузки на сотни МБ
ПостроительDOMвесь документ в памятипоиск элементов по именифайлы до десятков МБ, сложная вложенность
ФабрикаXDTOвесь документ в памятиобъекты со свойствамиесть XSD-схема, обмен по формату

Потоковое чтение: ЧтениеXML

Пусть файл выглядит так: <Товар Артикул="А-15"><Наименование>Бумага A4</Наименование></Товар>. Читаем атрибут и текст элемента:

Чтение = Новый ЧтениеXML;
Чтение.ОткрытьФайл(ИмяФайла);
Артикул = "";
Пока Чтение.Прочитать() Цикл
	Если Чтение.ТипУзла = ТипУзлаXML.НачалоЭлемента Тогда
		Если Чтение.Имя = "Товар" Тогда
			Артикул = Чтение.ПолучитьАтрибут("Артикул");
		ИначеЕсли Чтение.Имя = "Наименование" Тогда
			Чтение.Прочитать(); // переходим к текстовому узлу
			Если Чтение.ТипУзла = ТипУзлаXML.Текст Тогда
				Наименование = Чтение.Значение;
				Сообщить(Артикул + " — " + Наименование);
			КонецЕсли;
		КонецЕсли;
	КонецЕсли;
КонецЦикла;
Чтение.Закрыть();

Каждый вызов Прочитать() сдвигает курсор на следующий узел: начало элемента, текст, конец элемента. Поэтому значение элемента лежит не в самом узле Наименование, а в следующем за ним текстовом узле.

Через DOM: поиск по имени элемента

Если структура глубокая и нужно прыгать между ветками, проще загрузить документ в дерево:

Чтение = Новый ЧтениеXML;
Чтение.ОткрытьФайл(ИмяФайла);
Построитель = Новый ПостроительDOM;
Документ = Построитель.Прочитать(Чтение);
Чтение.Закрыть();

Для Каждого Узел Из Документ.ПолучитьЭлементыПоИмени("Товар") Цикл
	Артикул = Узел.ПолучитьАтрибут("Артикул");
	Текст = Узел.ТекстовоеСодержимое;
КонецЦикла;

ТекстовоеСодержимое склеивает текст всех вложенных узлов. Для элемента с одним вложенным Наименование это ровно его значение; для сложного узла лучше спуститься к нужному дочернему элементу.

XDTO и JSON

Когда к файлу есть XSD-схема, удобнее ФабрикаXDTO.ПрочитатьXML(Чтение, Тип): на выходе объект, у которого элементы доступны как свойства. Это путь для обменов по утверждённым форматам.

JSON читают похоже на XML, только объектом ЧтениеJSON:

Чтение = Новый ЧтениеJSON;
Чтение.ОткрытьФайл(ИмяФайла);
Данные = ПрочитатьJSON(Чтение, Истина); // Истина — получить Соответствие
Чтение.Закрыть();

Второй параметр Истина нужен, если ключи в JSON содержат пробелы или символы, недопустимые в именах свойств структуры.

Двоичные данные и потоки: чтение файлов любого формата

Картинки, PDF, архивы и файлы без понятной структуры читают как набор байтов.

ДвоичныеДанные: файл целиком

Данные = Новый ДвоичныеДанные(ИмяФайла);
РазмерБайт = Данные.Размер();
Адрес = ПоместитьВоВременноеХранилище(Данные, УникальныйИдентификатор);

Так файл прикладывают к справочнику, кладут в хранилище значения или передают между клиентом и сервером. Из двоичных данных можно получить текст: ПолучитьСтрокуИзДвоичныхДанных(Данные, КодировкаТекста.UTF8). Или открыть поток Данные.ОткрытьПотокДляЧтения() и передать его в ЧтениеТекста — оно принимает поток вместо имени файла. Тогда временный файл на диске не нужен.

Потоки и ЧтениеДанных

Потоковые объекты появились в 8.3.9. Они читают файл кусками и не загружают его в память. Пример: проверяем по первым байтам, что присланный «xlsx» — действительно ZIP-архив (сигнатура PK, байты 80 и 75):

Поток = ФайловыеПотоки.ОткрытьДляЧтения(ИмяФайла);
Чтение = Новый ЧтениеДанных(Поток);
Байт1 = Чтение.ПрочитатьБайт();
Байт2 = Чтение.ПрочитатьБайт();
Чтение.Закрыть();
Поток.Закрыть();
ЭтоАрхив = (Байт1 = 80 И Байт2 = 75);

Большой файл читают блоками через буфер:

Поток = ФайловыеПотоки.ОткрытьДляЧтения(ИмяФайла);
Буфер = Новый БуферДвоичныхДанных(65536); // 64 КБ
Прочитано = Поток.Прочитать(Буфер, 0, Буфер.Размер);
Пока Прочитано > 0 Цикл
	// обработка первых Прочитано байт буфера
	Прочитано = Поток.Прочитать(Буфер, 0, Буфер.Размер);
КонецЦикла;
Поток.Закрыть();

Метод потока Прочитать возвращает число реально прочитанных байт. На последнем блоке оно меньше размера буфера, поэтому обрабатывайте ровно Прочитано байт, а не весь буфер.

Кодировки, пути и где выполняется код

Когда код чтения написан верно, а файл всё равно не читается, причину почти всегда ищут в этих трёх местах.

Кодировка

Кодировку указывайте явно вторым параметром. Перечисление КодировкаТекста содержит UTF8, ANSI (в русской Windows это windows-1251), OEM (cp866), UTF16 и Системная. Можно передать и строку: "windows-1251", "UTF-8".

Как узнать ошибку кодировки по виду текста:

  • 🔤 Привет вместо «Привет» — файл в UTF-8, а читаете как ANSI;
  • ❓ ромбики с вопросом � — файл в windows-1251, а читаете как UTF-8;
  • 📟 буквы вроде ЏаЁўҐв — файл в OEM (так пишут старые консольные программы и bat-файлы).

Выгрузки из Excel «CSV (разделители — запятые)» в русской Windows обычно сохраняются в windows-1251, а «CSV UTF-8» — в UTF-8 с меткой BOM. Если источник неизвестен, прочитайте первые три байта через ЧтениеДанных: 239, 187, 191 означают BOM UTF-8.

Путь к файлу

  • 🖥️ Код на сервере видит диски сервера 1С, а не компьютера пользователя. Путь C:\Users\buh\Desktop\price.csv в серверной процедуре ищется на сервере, где такой папки нет.
  • 🐧 Если сервер на Linux, пути пишутся через / и чувствительны к регистру: Price.csv и price.csv — разные файлы.
  • 🌐 Сетевая папка \\fileserver\obmen доступна серверу только от имени учётной записи, под которой запущена служба агента сервера 1С. Права пользователя Windows здесь не помогают.
  • 🔀 Разделитель пути для текущей ОС возвращает ПолучитьРазделительПути().

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

Типовая схема для управляемых форм:

  1. На клиенте пользователь выбирает файл, и он помещается во временное хранилище (НачатьПомещениеФайлов или асинхронный ПоместитьФайлНаСерверАсинх в новых версиях платформы).
  2. На сервер передаётся адрес. Там ПолучитьИзВременногоХранилища(Адрес) возвращает ДвоичныеДанные.
  3. Данные пишут во временный файл ПолучитьИмяВременногоФайла("csv") или сразу открывают поток ОткрытьПотокДляЧтения().
  4. После чтения временный файл удаляют: УдалитьФайлы(ИмяВременногоФайла).

В веб-клиенте прямого доступа к диску пользователя нет вообще, поэтому этот путь — единственный рабочий.

Обработка ошибок при чтении и скорость

Проверка и перехват ошибок

Перед открытием проверьте, что файл есть:

Файл = Новый Файл(ИмяФайла);
Если Не Файл.Существует() Тогда
	Сообщить("Файл не найден: " + ИмяФайла);
	Возврат;
КонецЕсли;

Само чтение оборачивайте в Попытка, и закрывайте файл в обеих ветках. Иначе после ошибки файл останется занятым до завершения сеанса:

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

Типичные причины исключения при открытии:

  • 🔒 файл открыт в Excel — он держит книгу и CSV в монопольном режиме, закройте его;
  • 🚫 у службы сервера 1С нет прав на папку;
  • 📁 опечатка в пути или файл лежит на другой машине;
  • 🧩 в XML нарушена структура — ЧтениеXML упадёт на строке с ошибкой, и номер строки будет в тексте исключения.

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

  • 📏 Для файлов больше нескольких десятков мегабайт — только ЧтениеТекста, ЧтениеXML или потоки. ТекстовыйДокумент и DOM держат всё в памяти рабочего процесса.
  • 🗂️ Не делайте запрос к базе на каждой строке файла. Сначала соберите артикулы в ТаблицаЗначений, потом одним запросом найдите все элементы справочника.
  • 🧱 Записывайте объекты пачками по 500–1000 штук внутри транзакции, а не одной транзакцией на весь файл: длинная транзакция держит блокировки и мешает другим пользователям.
  • ⚙️ Тяжёлую загрузку запускайте на сервере, а лучше фоновым заданием, чтобы клиент не висел.
  • 🔁 Сложение строк Поле = Поле + Символ на очень длинных строках медленное. Если в CSV строки по тысячи символов, разбирайте строку функциями СтрНайти и Сред по позициям разделителей.
Перед запуском загрузки из файла
Выполнено: 0 / 6

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

Можно ли прочитать файл, который сейчас открыт другой программой?
Если программа открыла его только на чтение — да. Если файл держит Excel или другая программа в монопольном режиме, 1С получит ошибку доступа. Скопируйте файл с помощью КопироватьФайл или попросите закрыть его.
Как прочитать файл с FTP или по ссылке?
Объектами чтения файлов — никак, им нужен локальный путь или поток. Сначала скачайте файл через HTTPСоединение или FTPСоединение во временный файл, а затем читайте его обычным способом.
Как прочитать только последние строки большого лога?
Откройте ФайловыйПоток, перейдите ближе к концу методом Перейти и прочитайте хвост. Читать весь файл ради последних 100 строк незачем.
Чем ЧтениеТекста отличается от ЧтениеДанных?
ЧтениеТекста работает с символами и строками в заданной кодировке. ЧтениеДанных работает с байтами и числами, подходит для двоичных форматов и проверки сигнатур.
Почему в первой строке CSV лишние символы перед заголовком?
Это метка BOM в начале UTF-8 файла, прочитанного в кодировке ANSI. Откройте файл в кодировке UTF-8 — метка исчезнет.