При работе с внешними данными в формате DBF разработчики часто сталкиваются с проблемой неверного отображения кириллицы. В системе 1С:Предприятие объект XBase поддерживает два основных типа кодировки: ANSI (Windows-1251) и OEM (DOS CP866). Если кодировка указана неверно, вместо текста пользователь увидит нечитаемые символы («крякозябры»).
В данной статье мы разберем, как реализовать механизм выбора кодировки пользователем, рассмотрим способы программного обращения к системным перечислениям и изучим методы автоматического определения кодировки файла, чтобы минимизировать ошибки ручного ввода.
Самый простой и понятный для пользователя способ — добавление на форму обработки реквизита с типом Строка или Число, который будет связан с выпадающим списком. Рассмотрим ситуацию, когда на форме создан реквизит ВыбраннаяКодировка со списком выбора «ANSI» и «OEM».
Проанализируем программный код, который позволит применить выбранное значение к объекту XBase:
// Предположим, что переменная "фКодировка" содержит строку "ANSI" или "OEM"
ФайлDBF = Новый XBase;
Если фКодировка = "ANSI" Тогда
ФайлDBF.Кодировка = КодировкаXBase.ANSI;
ИначеЕсли фКодировка = "OEM" Тогда
ФайлDBF.Кодировка = КодировкаXBase.OEM;
Иначе
Предупреждение("Кодировка не выбрана, будет использована ANSI по умолчанию.");
ФайлDBF.Кодировка = КодировкаXBase.ANSI;
КонецЕсли;
ФайлDBF.ОткрытьФайл(ПутьКФайлу);
Этот метод надежен и прост в отладке, однако он требует написания громоздких условий, если вариантов выбора становится больше (хотя для XBase их всего два).
Существует более изящный способ, позволяющий избежать использования конструкций Если ... Тогда. Мы можем обратиться к системному перечислению КодировкаXBase как к коллекции, используя строковое представление имени значения в квадратных скобках. Это удобно, если значения в вашем списке выбора на форме в точности совпадают с именами значений перечисления в метаданных.
Рассмотрим пример реализации:
// Если в переменной ТекКодировка хранится строка "ANSI" или "OEM"
ФайлDBF = Новый XBase;
Попытка
ФайлDBF.Кодировка = КодировкаXBase[ТекКодировка];
Исключение
Сообщить("Некорректное имя кодировки: " + ТекКодировка);
КонецПопытки;
Важный нюанс: при использовании этого метода необходимо следить за регистром и языком написания. Значение в квадратных скобках должно строго соответствовать имени идентификатора в платформе (например, только латиница "ANSI" или "OEM").
Чтобы избавить пользователя от необходимости гадать, в какой кодировке сохранен файл, мы можем попытаться определить её программно. В спецификации формата DBF за кодировку отвечает 29-й байт заголовка (так называемый Language Driver ID). Хотя не все программы корректно заполняют это поле, в большинстве случаев оно содержит верную информацию.
Разберем, как прочитать этот байт, не открывая файл через XBase:
Функция ОпределитьКодировкуПоЗаголовку(ПутьКФайлу)
Чтение = Новый ЧтениеДанных(ПутьКФайлу);
// Пропускаем первые 29 байт
Чтение.Пропустить(29);
// Читаем 1 байт идентификатора кодировки
БайтКодировки = Чтение.ПрочитатьВБуфер(1).Получить(0);
Чтение.Закрыть();
// 0x65 (101) - Windows-1251 (ANSI)
// 0x26 (38) - CP866 (OEM)
Если БайтКодировки = 101 Тогда
Возврат КодировкаXBase.ANSI;
ИначеЕсли БайтКодировки = 38 Тогда
Возврат КодировкаXBase.OEM;
Иначе
// Если заголовок не определен, возвращаем ANSI как наиболее частую
Возврат КодировкаXBase.ANSI;
КонецЕсли;
КонецФункции
Если заголовок файла пуст или содержит неверные данные, мы можем прибегнуть к анализу содержимого. Идея заключается в том, чтобы прочитать первую строку данных и проверить коды символов. Русские буквы в разных кодировках занимают разные числовые диапазоны.
Проанализируем логику проверки:
ANSI.КодСимвола().OEM (CP866), но в ANSI выглядят как странные значки — значит, файл в кодировке OEM.Пример кода для частотного анализа:
Функция ЭтоКодировкаOEM(СтрокаДляПроверки)
Для Поз = 1 По СтрДлина(СтрокаДляПроверки) Цикл
Код = КодСимвола(СтрокаДляПроверки, Поз);
// В CP866 русские буквы начинаются с 128
// В Windows-1251 русские буквы начинаются с 192
// Если видим много символов в диапазоне 128-175, скорее всего это OEM
Если Код >= 128 И Код <= 175 Тогда
Возврат Истина;
КонецЕсли;
КонецЦикла;
Возврат Ложь;
КонецФункции
Разберем ситуацию, когда файл DBF сопровождается индексными файлами (.cdx или .ntx). Порядок сортировки строк в индексе напрямую зависит от кодировки. Если вы открываете файл в ANSI, а индексы были построены в OEM, поиск по индексу и методы Найти(), УстановитьФильтр() будут работать некорректно или возвращать пустые результаты.
Что нужно сделать:
Переиндексация(), чтобы избежать порчи индексных файлов.Если стандартный объект XBase не справляется (например, если файл поврежден или использует специфическую кодовую страницу, отличную от ANSI/OEM), можно использовать механизм ActiveX Data Objects (ADO). Этот метод позволяет более гибко настраивать параметры подключения через ConnectionString, указывая конкретного провайдера данных (например, Microsoft Jet 4.0 или Visual FoxPro Driver) и кодовую страницу.
Однако для большинства типовых задач в 1С объект XBase остается наиболее производительным и простым инструментом, если правильно управлять свойством Кодировка.