Поток в 1С оборвался: разбираем сообщения и чиним чтение-запись
Содержание
Ошибка потока в 1С почти всегда означает одно: код обращается к объекту-потоку (ФайловыйПоток, ПотокВПамяти) не так, как тот открыт. Читает из потока, открытого только на запись. Пишет в поток, открытый на чтение. Или трогает поток, который уже закрыт либо указывает на файл, занятый другим процессом.
У разработчика это выглядит буднично: вчера обработка обмена отработала, сегодня падает на строке с Новый ФайловыйПоток, а в служебном сообщении — «поток не поддерживает запись» или «процесс не может получить доступ к файлу». У администратора похоже выглядит сбой фонового задания: регламентная выгрузка завершается аварийно, в журнале регистрации — обрыв работы с потоком данных.
Ниже — что платформа называет потоком, какие сообщения она выдаёт, как за пару минут найти причину и починить чтение-запись, не наступая на те же грабли повторно.
Что в 1С называют потоком и почему он обрывается
В платформе 8.3 слово «поток» относится к объектам работы с бинарными и текстовыми данными. Это абстрактный Поток и две его конкретные реализации:
- 📄
ФайловыйПоток— чтение и запись файла на диске без полной загрузки его в память. - 🧠
ПотокВПамяти— буфер в оперативной памяти, удобен для сборки данных «на лету».
Поверх потока работают «читатели» и «писатели»: ЧтениеДанных / ЗаписьДанных для бинарных данных и ЧтениеТекста / ЗаписьТекста для текста. Они и порождают большую часть сообщений «ошибка потока», потому что их поведение жёстко зависит от того, в каком режиме поток открыт.
Реже под «потоком» понимают фоновое задание на сервере — оно действительно выполняется в отдельном потоке ОС. Если «упал поток» в этом смысле, причину ищут не в коде работы с файлами, а в журнале регистрации по событию фонового задания (см. раздел про диагностику).
На практике потоки всплывают в типовых местах: выгрузка и загрузка файлов обмена, сохранение присоединённых файлов и сканов, запись печатных форм на диск, разбор полученных по сети данных. Везде, где данные идут порциями, а не берутся из базы напрямую, работает поток — и там же появляется его ошибка.
Поток «обрывается» в трёх базовых ситуациях: режим доступа не совпал с операцией, поток уже закрыт (или ещё не открыт), либо файл физически недоступен — нет прав, нет самого файла или его держит другой сеанс. Всё остальное — частные случаи этих трёх.
Какие сообщения выдаёт платформа и что они значат
Текст в служебных сообщениях короткий, и по нему почти всегда видно класс проблемы. Разберём частые формулировки.
- 🔴 «поток не поддерживает запись» — поток открыт с
РежимДоступаКФайлу.Чтение, а код вызывает запись. Классика при копировании чужого примера. - 🔴 «поток не поддерживает чтение» — зеркальный случай: открыли на запись, пытаемся читать.
- 🔴 «поток не поддерживает установку позиции» — вызов перехода по позиции для потока, который этого не умеет (например, некоторые сетевые источники читаются только последовательно).
- 🔴 «Процесс не может получить доступ к файлу, так как этот файл занят другим процессом» — предыдущий поток не закрыли, файл остался заблокированным; либо его открыл Excel, антивирус, другой сеанс 1С.
- 🔴 «Значение не является значением объектного типа
» на операции чтения/записи — обращение к переменной потока после
Закрыть(), когда объект уже недоступен.
Текст сообщения — это уже половина диагноза. Прежде чем лезть в отладчик, прочитайте его дословно: «не поддерживает» указывает на режим, «занят другим процессом» — на блокировку, «не найден» — на путь и права.
Почему возникает ошибка потока
Причин немного, и почти все сводятся к рассогласованию между тем, как поток открыли, и тем, что с ним делают.
- Режим открытия не совпал с операцией. Самая частая причина. Поток открыли на чтение, а в него пишут — или наоборот.
- Поток не закрыт.
Закрыть()не вызвали (или код упал до него по исключению), файл остался заблокированным до завершения сеанса. - Повторное обращение к закрытому потоку. После
Закрыть()переменную используют снова. - Нет файла или нет прав. На сервере 1С путь существует не на клиентской машине, а на сервере, и под служебной учётной записью прав на папку может не быть.
- Неверная кодировка текста. Для
ЧтениеТекста/ЗаписьТекстауказали не туКодировкаТекста— файл читается кракозябрами или падает на спецсимволах. - Клиент и сервер перепутаны.
ФайловыйПотокна сервере видит файловую систему сервера, а не пользователя. ПутьC:\Обменна машине бухгалтера и на сервере — это разные папки.
На клиент-серверной базе путь к файлу почти всегда относится к серверу. Если выгрузка должна лечь на диск пользователя, данные передают на клиент (например, через временное хранилище), а уже там сохраняют.
Диагностика: как быстро найти причину
Порядок действий — от простого к сложному, чтобы не тратить время на отладчик там, где достаточно прочитать путь.
- Прочитайте сообщение целиком. Определите класс по словам: «не поддерживает» → режим, «занят» → блокировка, «не найден» / «отказано» → путь и права.
- Найдите строку. В конфигураторе откройте модуль, где падает код, и посмотрите, с каким режимом открыт поток и где стоит
Закрыть(). - Проверьте путь руками. Откройте указанную папку на той машине, где выполняется код. Для серверного кода это сервер 1С, а не ваш компьютер.
- Посмотрите журнал регистрации. Раздел
Администрирование → Журнал регистрации. Для фонового задания фильтруйте по событию фоновых заданий — там видно, на какой строке оборвалось выполнение. - Проверьте блокировку файла. Если файл «занят», на Windows Server посмотрите, какой процесс держит его (диспетчер задач, монитор ресурсов). Часто это второй сеанс 1С или открытый вручную файл.
- Воспроизведите в отладчике. Поставьте точку останова на строке создания потока, в режиме отладки проверьте значения переменных до и после
Закрыть().
Для фоновых заданий состав завершённых и аварийных можно получить программно через ФоновыеЗадания.ПолучитьФоновыеЗадания(...) и статус СтатусФоновогоЗадания. Задание со статусом ЗавершеноАварийно хранит текст ошибки — это и есть ваш обрыв потока.
Отдельная подсказка по времени: если поток падает нерегулярно, запишите в журнал момент открытия и закрытия каждого файла. Когда обрыв совпадает по времени с проходом антивируса или резервным копированием, причина не в коде — внешняя программа коротко блокирует файл, и ваш Новый ФайловыйПоток попадает ровно в это окно.
Как устранить ошибку потока
Чаще всего правка — одна строка. Разберём по типам.
Неверный режим доступа. Откройте поток так, как собираетесь его использовать:
// Запись: открыть или создать файл, режим доступа — запись
Поток = Новый ФайловыйПоток(
"C:\Обмен\out.xml",
РежимОткрытияФайла.ОткрытьИлиСоздать,
РежимДоступаКФайлу.Запись);
Чтобы не гадать с режимами, держите перед глазами простое соответствие «что делаю → как открываю»:
| Что делаю с файлом | Режим открытия | Режим доступа |
|---|---|---|
| Только читаю существующий | Открыть | Чтение |
| Пишу с нуля (перезаписать) | Создать | Запись |
| Дописываю в конец | Добавление | Запись |
| Читаю и правлю на месте | ОткрытьИлиСоздать | ЧтениеИЗапись |
Режим Создать затирает существующий файл без предупреждения, поэтому для дозаписи логов берут Добавление, а не Создать. Режим СоздатьНовый упадёт, если файл уже есть, — это удобно, когда перезапись недопустима.
Поток не закрыт. Закрывайте его в любой ветке, в том числе при исключении. Шаблон с Попытка:
Запись = Новый ЗаписьТекста("C:\Обмен\log.txt", КодировкаТекста.UTF8);
Попытка
Запись.ЗаписатьСтроку("Выгрузка завершена");
Исключение
Запись.Закрыть();
ВызватьИсключение;
КонецПопытки;
Запись.Закрыть();
Так файл освобождается даже тогда, когда внутри случилась ошибка.
Повторное обращение к закрытому потоку. Уберите лишний Закрыть() или откройте поток заново перед следующей операцией. После Закрыть() объект использовать нельзя. Частая ловушка — закрыть поток внутри цикла, а на второй итерации снова в него писать: выносите открытие за пределы цикла, а закрытие — после него.
Если целиком файл помещается в память, потоки часто вообще не нужны — проще прочитать файл одним вызовом:
Данные = Новый ДвоичныеДанные("C:\Обмен\in.xml");
Это убирает весь класс ошибок «поток не поддерживает…» — вы просто не работаете с потоком. Потоки оставляйте для больших файлов и построчной обработки.
Неверная кодировка. Задавайте её явно при чтении и записи текста: КодировкаТекста.UTF8 для современных обменов, КодировкаТекста.ANSI или нужную кодовую страницу — для старых выгрузок. Если читаете чужой файл и видите кракозябры, подберите кодировку, которой он реально записан. Отдельный нюанс — UTF-8 с BOM: лишние служебные байты в начале файла ломают разбор у придирчивого приёмника, поэтому для внешних систем уточняйте, ждут они файл с BOM или без него, и записывайте соответствующе.
Нет прав или файла. Проверьте, под какой учётной записью работает сервер 1С, и дайте ей права на папку обмена. Для сетевых путей используйте UNC-путь вида \\сервер\обмен, а не подключённый диск Z: — подключённые диски служебной учётной записи обычно не видны.
Поток из HTTP-обмена. При выгрузке и загрузке через HTTPСоединение тело ответа тоже приходит потоком или двоичными данными. Если обмен падает с «ошибкой потока», проверьте не свой код записи, а что сервер-источник вообще вернул файл: пустой или оборванный ответ даёт тот же обрыв на чтении. Логируйте код ответа и размер данных до того, как начать их разбирать.
Как не допустить обрыва потока
Профилактика сводится к дисциплине работы с ресурсами. Правила простые, но их легко забыть под дедлайн.
- ✅ Открывайте поток ровно под нужную операцию — не берите
ЧтениеИЗапись, если только читаете. - ✅ Всегда закрывайте поток, в том числе в ветке
Исключение. - ✅ Для временных файлов берите
ПолучитьИмяВременногоФайла()и удаляйте их черезУдалитьФайлы()после работы. - ✅ Небольшие файлы читайте целиком в
ДвоичныеДанные, потоки держите для крупных. - ✅ На клиент-серверной базе помните: серверный код видит файловую систему сервера.
Если регламентное задание работает с одним и тем же файлом, добавьте проверку: не занят ли файл, и повтор через паузу. Так разовая блокировка сторонним процессом не будет ронять всю выгрузку.
Частые вопросы
Почему код падает на сервере, хотя на клиенте в толстом клиенте всё работает?
ФайловыйПоток в серверном контексте обращается к файловой системе сервера 1С, а не вашего компьютера. Путь C:\Обмен на сервере — это другая папка, и прав у служебной учётной записи там может не быть.Чем поток отличается от ДвоичныхДанных?
ДвоичныеДанные загружают файл целиком в память одним вызовом. Поток читает и пишет порциями, не держа весь файл в памяти, — это важно для больших файлов, но добавляет требований к режиму доступа и закрытию.Нужно ли закрывать ПотокВПамяти, если он не связан с файлом?
Что делать, если файл «занят другим процессом» и закрыть его в коде нечего?
Можно ли читать поток частями, если он «не поддерживает установку позиции»?
ПотокВПамяти или в ДвоичныеДанные.