При интеграции 1С с внешними системами разработчики часто сталкиваются с необходимостью импорта данных из файлов старого формата DBF. Нередко возникает крайне неприятная ситуация: один и тот же DBF-файл на одном и том же компьютере идеально читается в файловой базе 1С, но при попытке загрузить его в клиент-серверной базе (на SQL-сервере) вместо привычного русского текста мы получаем нечитаемые символы («кракозябры»).
В этой статье мы подробно разберем, почему возникает эта проблема, проанализируем архитектурные особенности выполнения кода на сервере и рассмотрим несколько надежных способов исправления кодировки — от простых административных настроек Windows до продвинутых кроссплатформенных методов программирования.
Для того чтобы понять корень проблемы, проанализируем разницу в архитектуре выполнения кода между файловым и клиент-серверным вариантами работы 1С:
rphost на стороне сервера приложений 1С. Этот процесс запускается от имени специальной системной учетной записи (например, USR1CV8 или NetworkService).По умолчанию у служебных учетных записей Windows нет полноценного интерактивного профиля пользователя. Они используют региональные настройки «по умолчанию» (System Locale). Если операционная система сервера изначально была англоязычной (что крайне распространено для дистрибутивов Windows Server), или если при первоначальной настройке системы параметры русской локализации не были скопированы для системных профилей, служба 1С будет использовать американскую кодовую страницу (CP1252 для ANSI и CP437/CP850 для OEM/DOS). Как результат — русские буквы при чтении превращаются в хаотичный набор символов.
Часто разработчики пытаются решить проблему «в лоб», прописывая кодировку в коде 1С до или после открытия файла:
ФайлDBF = Новый XBase;
ФайлDBF.Кодировка = КодировкаXBase.OEM;
ФайлDBF.ОткрытьФайл(ПутьКФайлу);
Однако на сервере SQL это действие не приносит результата. Дело в том, что встроенный объект 1С XBase не содержит в себе собственных жестко зашитых таблиц перекодирования для всех устаревших страниц. Для конвертации символов DOS (CP866) в Юникод он обращается к стандартным функциям Windows API.
Если в окружении процесса rphost системной OEM-кодировкой по умолчанию назначена латиница (например, CP850), то операционная система выполняет трансляцию байтов именно по латинской таблице. Платформа 1С получает от ОС уже искаженные данные, и никакие дальнейшие манипуляции со свойством Кодировка исправить этот результат уже не могут.
Самый простой и правильный путь решения проблемы на уровне операционной системы — это корректная настройка локали для всех пользователей, включая системные службы Windows Server. Разберем этот процесс по шагам:
После перезагрузки служба сервера 1С начнет инициализироваться с правильной системной локалью, и чтение файлов через XBase в кодировке OEM станет корректным.
Если по соображениям безопасности или корпоративным стандартам вам запрещено глобально менять локаль сервера или копировать параметры на экран приветствия, можно прибегнуть к «точечной» настройке через системный реестр. Мы можем заставить Windows принудительно сопоставлять запросы к латинским таблицам с кириллическими файлами перекодировки.
Для реализации этого метода выполним следующие шаги:
regedit).HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Nls\CodePage1250 — установим значение c_1251.nls1252 (дефолтная латиница Windows) — установим значение c_1251.nls850 (дефолтная OEM-кодировка DOS) — установим значение c_866.nls437 — установим значение c_866.nlsПосле этого любые системные запросы на декодирование латинских страниц будут автоматически перенаправляться на кириллические таблицы ANSI (CP1251) и DOS (CP866).
Иногда кодировка отображается неверно из-за структуры самого загружаемого DBF-файла. В заголовке любого DBF-файла, в его 29-м байте, хранится специальный маркер — Language Driver ID (LDID), который указывает программам, какую кодировку использовать при чтении.
Проанализируем возможные значения этого байта:
0x00 — кодовая страница не определена. В этом случае драйверы ОС и платформа 1С будут пытаться применить дефолтную кодовую страницу системы (что на сервере без настроенной локали приведет к сбою).0x65 (101 в десятичной системе) — явное указание русской DOS-кодировки (CP866).0xC9 (201 в десятичной системе) — явное указание русской Windows-кодировки (CP1251).Если внешняя программа выгружает файлы с нулевым 29-м байтом, рекомендуется либо настроить эту программу на корректную запись LDID, либо воспользоваться специализированными утилитами (например, DBF Commander) для автоматического прописывания корректного языкового драйвера в заголовок файла перед его отправкой в 1С.
Если в вашем решении загрузка DBF-файлов реализована не через встроенный объект XBase, а посредством внешних COM-объектов (Microsoft Jet OLEDB или Access Connectivity Engine), то настройки кодировки регулируются другими ключами реестра.
Параметры работы этих драйверов с DBF-файлами находятся по следующему пути (для 64-битных систем): HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Jet\4.0\Engines\Xbase (или в аналогичной ветке Wow6432Node для 32-битных процессов).
В этой ветке найдем строковый параметр DataCodePage. По умолчанию он может иметь значение OEM. Чтобы избежать проблем с системной кодировкой, мы можем принудительно установить его в значение ANSI или явно определить используемую кодовую страницу прямо в строке подключения ADO, добавив параметры:
"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\Folder;Extended Properties=""DBASE IV;CharacterSet=CP866;"""
В современных реалиях сервер 1С часто работает под управлением операционных систем семейства Linux, где манипуляции с реестром Windows неприменимы. Чтобы сделать ваш код загрузки DBF абсолютно стабильным, независимым от настроек операционной системы, прав пользователей и используемой СУБД, настоятельно рекомендуется отказаться от использования стандартного объекта XBase и COM-объектов на сервере.
Вместо этого мы можем читать DBF-файл как двоичные данные и самостоятельно парсить его структуру. Так как формат DBF строго документирован, это не представляет большой сложности. При конвертации считанных байтовых массивов в строки 1С мы можем жестко задать нужную кодировку без оглядки на операционную систему.
Рассмотрим пример того, как можно реализовать чтение файла в двоичном режиме:
// Открываем DBF-файл как поток двоичных данных
ДвоичныеДанныеФайла = Новый ДвоичныеДанные(ПутьКФайлу);
ПотокЧтения = ДвоичныеДанныеФайла.ОткрытьПотокДляЧтения();
// Пример чтения заголовка и побайтового разбора данных:
// Мы можем читать блоки байт и конвертировать их в строки с жестким указанием кодировки
ИмяКодировки = "cp866"; // Гарантирует корректное чтение DOS-кодировки даже на Linux
// Для конвертации буфера байт в строку используем метод ПолучитьСтрокуИзБуфераОбмена
// ТекстСтроки = ПолучитьСтрокуИзБуфера(БуферБайт, ИмяКодировки);
ПотокЧтения.Закрыть();
Этот метод работает полностью в оперативной памяти сервера 1С, гарантирует 100% предсказуемый результат и избавляет системных администраторов от необходимости тонкой настройки локали и реестра операционной системы сервера.