При работе со встроенным в 1С объектом XBase разработчики часто сталкиваются с неприятной ошибкой: «Ошибка при вызове метода контекста (ОткрытьФайл): Длина имени файла превысила 8 символов». Данная проблема унаследована от старого стандарта СУБД dBase (формат DOS 8.3), который жестко ограничивает длину имени файла восемью символами, а расширения — тремя.
Попытки обойти это ограничение с помощью вызова системной функции Windows ShortPath через COM-объект Scripting.FileSystemObject часто приводят к нестабильной работе: у одних клиентов обработка открывает файлы без проблем, а у других тот же самый код выдает фатальную ошибку. В этой статье мы подробно разберем, почему так происходит, и рассмотрим три надежных способа решения этой проблемы.
Конструкция вида fso.GetFile(ПутьБДШ).ShortPath запрашивает у операционной системы Windows короткое имя файла (например, превращает 000001000005000.dbf в 000001~1.DBF). Однако этот «костыль» ломается, если сама операционная система на конкретном компьютере не сгенерировала короткое имя. Проанализируем основные причины, почему это происходит:
NtfsDisable8dot3NameCreation. Если он равен 1 или 2, короткие имена могут не создаваться.ShortPath всегда будет возвращать длинный путь, так как эти системы в принципе не поддерживают стандарт 8.3.ShortPath зависит от настроек удаленного сервера. Если сетевой диск работает под управлением Linux (Samba) или файловая система сетевого хранилища не настроена на передачу коротких имен, метод вернет длинный путь.ShortPath короткие имена должны быть сгенерированы для абсолютно каждого каталога в пути к файлу. Если хотя бы одна папка в пути (например, C:\Новая папка с длинным именем\file.dbf) была создана при отключенной поддержке 8.3, то весь путь не сможет быть сокращен.Ниже мы рассмотрим три способа решения этой проблемы, начиная с самого простого и надежного.
Это самый быстрый и гарантированный способ обойти ограничение XBase без вмешательства в настройки операционной системы клиентов. Мы просто создаем копию исходного файла в каталоге временных файлов, переименовывая его в случайное имя длиной не более 8 символов, обрабатываем его и затем удаляем.
Разберем по шагам реализацию этого механизма в коде 1С:
// Очищаем имя от пути и расширения для анализа
ФайлИсточник = Новый Файл(ПутьБДШ);
КаталогИсточника = ФайлИсточник.Путь;
// Генерируем уникальное имя длиной строго до 8 символов
// Стандартный ГУИД отлично подходит, если взять от него первые 8 символов
УникальныйПрефикс = Лев(Строка(Новый УникальныйИдентификатор()), 8);
ИмяВременногоФайла = УникальныйПрефикс + ".dbf";
ПутьКВременномуФайлу = КаталогВременныхФайлов() + ИмяВременногоФайла;
// Копируем исходный файл во временный каталог
Попытка
КопироватьФайл(ПутьБДШ, ПутьКВременномуФайлу);
Исключение
ВызватьИсключение "Не удалось скопировать файл во временный каталог: " + ОписаниеОшибки();
КонецПопытки;
// Работаем с временным файлом через стандартный XBase
БДШ = Новый XBase;
БДШ.ОтображатьУдаленные = Ложь;
БДШ.Кодировка = КодировкаXBase.ANSI;
Попытка
БДШ.ОткрытьФайл(ПутьКВременномуФайлу,,0);
Если БДШ.Открыта() Тогда
// Выполняем чтение или запись данных
Пока БДШ.Следующая() Цикл
// Ваша логика обработки строк, например:
// КодНоменклатуры = БДШ.ПолучитьЗначение("CODE");
КонецЦикла;
БДШ.ЗакрытьФайл();
КонецЕсли;
Исключение
// В случае ошибки обязательно закрываем файл, чтобы не заблокировать его в системе
Если БДШ.Открыта() Тогда
БДШ.ЗакрытьФайл();
КонецЕсли;
// Удаляем временный файл перед вызовом исключения
УдалитьФайлы(ПутьКВременномуФайлу);
ВызватьИсключение "Ошибка при обработке DBF: " + ОписаниеОшибки();
КонецПопытки;
// Удаляем временный файл после успешного завершения работы
УдалитьФайлы(ПутьКВременномуФайлу);
Преимущества: Работает абсолютно на любых компьютерах, независимо от операционной системы, настроек реестра, прав доступа и типа файловой системы.
Если вы хотите полностью отказаться от устаревшего объекта XBase и не плодить временные файлы на диске, отличной альтернативой станет использование технологии ADO (ActiveX Data Objects). Microsoft Jet OLEDB драйвер позволяет работать с DBF-файлами как с таблицами базы данных с помощью обычных SQL-запросов. При этом ограничений на длину имени файла и пути к нему нет вообще.
Рассмотрим пример чтения данных через ADODB:
// Разделяем полный путь на каталог и имя файла
ФайлДанных = Новый Файл(ПутьБДШ);
КаталогПапки = ФайлДанных.Путь;
ИмяФайла = ФайлДанных.Имя;
Connection = Новый COMObject("ADODB.Connection");
Recordset = Новый COMObject("ADODB.Recordset");
// Формируем строку подключения. Указываем путь к папке как к источнику данных (Data Source)
СтрокаПодключения = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + КаталогПапки + ";Extended Properties=dBase IV;";
Попытка
Connection.Open(СтрокаПодключения);
Исключение
// Если Jet OLEDB не установлен (например, на 64-битных системах), пробуем ACE OLEDB
СтрокаПодключения = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + КаталогПапки + ";Extended Properties=dBase IV;";
Попытка
Connection.Open(СтрокаПодключения);
Исключение
Предупреждение("Не удалось подключить драйвер DBF: " + ОписаниеОшибки());
Возврат;
КонецПопытки;
КонецПопытки;
// Запрос к файлу DBF. Имя файла выступает в роли таблицы
ТекстЗапроса = "SELECT * FROM [" + ИмяФайла + "]";
Попытка
Recordset.Open(ТекстЗапроса, Connection);
Пока Recordset.EOF = 0 Цикл
// Доступ к полям по именам колонки
ЗначениеПоля = Recordset.Fields("ИмяПоля").Value;
// Переходим к следующей строке
Recordset.MoveNext();
КонецЦикла;
Recordset.Close();
Connection.Close();
Исключение
Если Connection.State = 1 Тогда
Connection.Close();
КонецЕсли;
Сообщить("Ошибка выполнения SQL-запроса к DBF: " + ОписаниеОшибки());
КонецПопытки;
Преимущества: Высокая скорость чтения больших объемов данных, возможность фильтрации и сортировки на уровне SQL-запроса, полное отсутствие проблем с длинными путями.
Если вы принципиально хотите оставить старый код без изменений и решить проблему системными методами на проблемных компьютерах, вам потребуется настроить генерацию имен 8.3 в операционной системе Windows.
Выполните следующие шаги на проблемном ПК:
Win + R, введите regedit и нажмите Enter).HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\FileSystem.NtfsDisable8dot3NameCreation. Установите его значение в 0 (включить создание коротких имен для всех томов) или 2 (определять параметры индивидуально для каждого тома).D:), откройте командную строку от имени Администратора и выполните команду проверки поддержки коротких имен:
fsutil 8dot3name query D:
fsutil 8dot3name set D: 0
ShortPath в 1С заработает корректно.Мы проанализировали причины сбоя при открытии DBF-файлов с длинными именами в 1С и изучили три способа решения проблемы. Наиболее универсальным и рекомендуемым является Решение 1 (создание временной копии с коротким именем) или переход на современную технологию ADODB, которая навсегда избавит вашу конфигурацию от зависимости от настроек операционной системы клиентов.