Поток в 1С оборвался: разбираем сообщения и чиним чтение-запись

· 9 мин

Содержание

Ошибка потока в 1С почти всегда означает одно: код обращается к объекту-потоку (ФайловыйПоток, ПотокВПамяти) не так, как тот открыт. Читает из потока, открытого только на запись. Пишет в поток, открытый на чтение. Или трогает поток, который уже закрыт либо указывает на файл, занятый другим процессом.

У разработчика это выглядит буднично: вчера обработка обмена отработала, сегодня падает на строке с Новый ФайловыйПоток, а в служебном сообщении — «поток не поддерживает запись» или «процесс не может получить доступ к файлу». У администратора похоже выглядит сбой фонового задания: регламентная выгрузка завершается аварийно, в журнале регистрации — обрыв работы с потоком данных.

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

Что в 1С называют потоком и почему он обрывается

В платформе 8.3 слово «поток» относится к объектам работы с бинарными и текстовыми данными. Это абстрактный Поток и две его конкретные реализации:

  • 📄 ФайловыйПоток — чтение и запись файла на диске без полной загрузки его в память.
  • 🧠 ПотокВПамяти — буфер в оперативной памяти, удобен для сборки данных «на лету».

Поверх потока работают «читатели» и «писатели»: ЧтениеДанных / ЗаписьДанных для бинарных данных и ЧтениеТекста / ЗаписьТекста для текста. Они и порождают большую часть сообщений «ошибка потока», потому что их поведение жёстко зависит от того, в каком режиме поток открыт.

Реже под «потоком» понимают фоновое задание на сервере — оно действительно выполняется в отдельном потоке ОС. Если «упал поток» в этом смысле, причину ищут не в коде работы с файлами, а в журнале регистрации по событию фонового задания (см. раздел про диагностику).

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

Поток «обрывается» в трёх базовых ситуациях: режим доступа не совпал с операцией, поток уже закрыт (или ещё не открыт), либо файл физически недоступен — нет прав, нет самого файла или его держит другой сеанс. Всё остальное — частные случаи этих трёх.

Какие сообщения выдаёт платформа и что они значат

Текст в служебных сообщениях короткий, и по нему почти всегда видно класс проблемы. Разберём частые формулировки.

  • 🔴 «поток не поддерживает запись» — поток открыт с РежимДоступаКФайлу.Чтение, а код вызывает запись. Классика при копировании чужого примера.
  • 🔴 «поток не поддерживает чтение» — зеркальный случай: открыли на запись, пытаемся читать.
  • 🔴 «поток не поддерживает установку позиции» — вызов перехода по позиции для потока, который этого не умеет (например, некоторые сетевые источники читаются только последовательно).
  • 🔴 «Процесс не может получить доступ к файлу, так как этот файл занят другим процессом» — предыдущий поток не закрыли, файл остался заблокированным; либо его открыл Excel, антивирус, другой сеанс 1С.
  • 🔴 «Значение не является значением объектного типа » на операции чтения/записи — обращение к переменной потока после Закрыть(), когда объект уже недоступен.
Диагностика: выберите симптом

Текст сообщения — это уже половина диагноза. Прежде чем лезть в отладчик, прочитайте его дословно: «не поддерживает» указывает на режим, «занят другим процессом» — на блокировку, «не найден» — на путь и права.

Почему возникает ошибка потока

Причин немного, и почти все сводятся к рассогласованию между тем, как поток открыли, и тем, что с ним делают.

  1. Режим открытия не совпал с операцией. Самая частая причина. Поток открыли на чтение, а в него пишут — или наоборот.
  2. Поток не закрыт. Закрыть() не вызвали (или код упал до него по исключению), файл остался заблокированным до завершения сеанса.
  3. Повторное обращение к закрытому потоку. После Закрыть() переменную используют снова.
  4. Нет файла или нет прав. На сервере 1С путь существует не на клиентской машине, а на сервере, и под служебной учётной записью прав на папку может не быть.
  5. Неверная кодировка текста. Для ЧтениеТекста / ЗаписьТекста указали не ту КодировкаТекста — файл читается кракозябрами или падает на спецсимволах.
  6. Клиент и сервер перепутаны. ФайловыйПоток на сервере видит файловую систему сервера, а не пользователя. Путь C:\Обмен на машине бухгалтера и на сервере — это разные папки.

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

Диагностика: как быстро найти причину

Порядок действий — от простого к сложному, чтобы не тратить время на отладчик там, где достаточно прочитать путь.

  1. Прочитайте сообщение целиком. Определите класс по словам: «не поддерживает» → режим, «занят» → блокировка, «не найден» / «отказано» → путь и права.
  2. Найдите строку. В конфигураторе откройте модуль, где падает код, и посмотрите, с каким режимом открыт поток и где стоит Закрыть().
  3. Проверьте путь руками. Откройте указанную папку на той машине, где выполняется код. Для серверного кода это сервер 1С, а не ваш компьютер.
  4. Посмотрите журнал регистрации. Раздел Администрирование → Журнал регистрации. Для фонового задания фильтруйте по событию фоновых заданий — там видно, на какой строке оборвалось выполнение.
  5. Проверьте блокировку файла. Если файл «занят», на Windows Server посмотрите, какой процесс держит его (диспетчер задач, монитор ресурсов). Часто это второй сеанс 1С или открытый вручную файл.
  6. Воспроизведите в отладчике. Поставьте точку останова на строке создания потока, в режиме отладки проверьте значения переменных до и после Закрыть().

Для фоновых заданий состав завершённых и аварийных можно получить программно через ФоновыеЗадания.ПолучитьФоновыеЗадания(...) и статус СтатусФоновогоЗадания. Задание со статусом ЗавершеноАварийно хранит текст ошибки — это и есть ваш обрыв потока.

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

Как устранить ошибку потока

Чаще всего правка — одна строка. Разберём по типам.

Неверный режим доступа. Откройте поток так, как собираетесь его использовать:

// Запись: открыть или создать файл, режим доступа — запись
Поток = Новый ФайловыйПоток(
    "C:\Обмен\out.xml",
    РежимОткрытияФайла.ОткрытьИлиСоздать,
    РежимДоступаКФайлу.Запись);

Чтобы не гадать с режимами, держите перед глазами простое соответствие «что делаю → как открываю»:

Что делаю с файломРежим открытияРежим доступа
Только читаю существующийОткрытьЧтение
Пишу с нуля (перезаписать)СоздатьЗапись
Дописываю в конецДобавлениеЗапись
Читаю и правлю на местеОткрытьИлиСоздатьЧтениеИЗапись

Режим Создать затирает существующий файл без предупреждения, поэтому для дозаписи логов берут Добавление, а не Создать. Режим СоздатьНовый упадёт, если файл уже есть, — это удобно, когда перезапись недопустима.

Поток не закрыт. Закрывайте его в любой ветке, в том числе при исключении. Шаблон с Попытка:

Запись = Новый ЗаписьТекста("C:\Обмен\log.txt", КодировкаТекста.UTF8);
Попытка
    Запись.ЗаписатьСтроку("Выгрузка завершена");
Исключение
    Запись.Закрыть();
    ВызватьИсключение;
КонецПопытки;
Запись.Закрыть();

Так файл освобождается даже тогда, когда внутри случилась ошибка.

Повторное обращение к закрытому потоку. Уберите лишний Закрыть() или откройте поток заново перед следующей операцией. После Закрыть() объект использовать нельзя. Частая ловушка — закрыть поток внутри цикла, а на второй итерации снова в него писать: выносите открытие за пределы цикла, а закрытие — после него.

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

Данные = Новый ДвоичныеДанные("C:\Обмен\in.xml");

Это убирает весь класс ошибок «поток не поддерживает…» — вы просто не работаете с потоком. Потоки оставляйте для больших файлов и построчной обработки.

Неверная кодировка. Задавайте её явно при чтении и записи текста: КодировкаТекста.UTF8 для современных обменов, КодировкаТекста.ANSI или нужную кодовую страницу — для старых выгрузок. Если читаете чужой файл и видите кракозябры, подберите кодировку, которой он реально записан. Отдельный нюанс — UTF-8 с BOM: лишние служебные байты в начале файла ломают разбор у придирчивого приёмника, поэтому для внешних систем уточняйте, ждут они файл с BOM или без него, и записывайте соответствующе.

Нет прав или файла. Проверьте, под какой учётной записью работает сервер 1С, и дайте ей права на папку обмена. Для сетевых путей используйте UNC-путь вида \\сервер\обмен, а не подключённый диск Z: — подключённые диски служебной учётной записи обычно не видны.

Поток из HTTP-обмена. При выгрузке и загрузке через HTTPСоединение тело ответа тоже приходит потоком или двоичными данными. Если обмен падает с «ошибкой потока», проверьте не свой код записи, а что сервер-источник вообще вернул файл: пустой или оборванный ответ даёт тот же обрыв на чтении. Логируйте код ответа и размер данных до того, как начать их разбирать.

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

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

  • ✅ Открывайте поток ровно под нужную операцию — не берите ЧтениеИЗапись, если только читаете.
  • ✅ Всегда закрывайте поток, в том числе в ветке Исключение.
  • ✅ Для временных файлов берите ПолучитьИмяВременногоФайла() и удаляйте их через УдалитьФайлы() после работы.
  • ✅ Небольшие файлы читайте целиком в ДвоичныеДанные, потоки держите для крупных.
  • ✅ На клиент-серверной базе помните: серверный код видит файловую систему сервера.
Проверка перед запуском обработки с потоками
Выполнено: 0 / 6

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

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

Почему код падает на сервере, хотя на клиенте в толстом клиенте всё работает?
ФайловыйПоток в серверном контексте обращается к файловой системе сервера 1С, а не вашего компьютера. Путь C:\Обмен на сервере — это другая папка, и прав у служебной учётной записи там может не быть.
Чем поток отличается от ДвоичныхДанных?
ДвоичныеДанные загружают файл целиком в память одним вызовом. Поток читает и пишет порциями, не держа весь файл в памяти, — это важно для больших файлов, но добавляет требований к режиму доступа и закрытию.
Нужно ли закрывать ПотокВПамяти, если он не связан с файлом?
Да. Закрытие освобождает память и переводит данные в итоговый результат. После закрытия обращаться к потоку уже нельзя — сохраните результат в переменную заранее.
Что делать, если файл «занят другим процессом» и закрыть его в коде нечего?
Файл держит внешняя программа или другой сеанс: открытый Excel, антивирус, второй экземпляр обработки. Найдите процесс монитором ресурсов на сервере и закройте его; в регламентных заданиях добавьте повтор с паузой.
Можно ли читать поток частями, если он «не поддерживает установку позиции»?
Читать последовательно — да, перематывать назад — нет. Такой поток обрабатывайте строго по порядку; если нужен произвольный доступ, сначала прочитайте данные в ПотокВПамяти или в ДвоичныеДанные.