Как предоставить пользователю выбор кодировки (ANSI или OEM) при работе с DBF-файлами через XBase?

Программист 1С v8.3 (Обычные формы) IT и автоматизация бизнеса
← На главную

При работе с внешними данными в формате DBF разработчики часто сталкиваются с проблемой неверного отображения кириллицы. В системе 1С:Предприятие объект XBase поддерживает два основных типа кодировки: ANSI (Windows-1251) и OEM (DOS CP866). Если кодировка указана неверно, вместо текста пользователь увидит нечитаемые символы («крякозябры»).

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

Способ 1. Реализация выбора через элементы формы и программные условия

Самый простой и понятный для пользователя способ — добавление на форму обработки реквизита с типом Строка или Число, который будет связан с выпадающим списком. Рассмотрим ситуацию, когда на форме создан реквизит ВыбраннаяКодировка со списком выбора «ANSI» и «OEM».

Проанализируем программный код, который позволит применить выбранное значение к объекту XBase:


// Предположим, что переменная "фКодировка" содержит строку "ANSI" или "OEM"
ФайлDBF = Новый XBase;

Если фКодировка = "ANSI" Тогда
    ФайлDBF.Кодировка = КодировкаXBase.ANSI;
ИначеЕсли фКодировка = "OEM" Тогда
    ФайлDBF.Кодировка = КодировкаXBase.OEM;
Иначе
    Предупреждение("Кодировка не выбрана, будет использована ANSI по умолчанию.");
    ФайлDBF.Кодировка = КодировкаXBase.ANSI;
КонецЕсли;

ФайлDBF.ОткрытьФайл(ПутьКФайлу);

Этот метод надежен и прост в отладке, однако он требует написания громоздких условий, если вариантов выбора становится больше (хотя для XBase их всего два).

Способ 2. Обращение к перечислению по строковому имени

Существует более изящный способ, позволяющий избежать использования конструкций Если ... Тогда. Мы можем обратиться к системному перечислению КодировкаXBase как к коллекции, используя строковое представление имени значения в квадратных скобках. Это удобно, если значения в вашем списке выбора на форме в точности совпадают с именами значений перечисления в метаданных.

Рассмотрим пример реализации:


// Если в переменной ТекКодировка хранится строка "ANSI" или "OEM"
ФайлDBF = Новый XBase;
Попытка
    ФайлDBF.Кодировка = КодировкаXBase[ТекКодировка];
Исключение
    Сообщить("Некорректное имя кодировки: " + ТекКодировка);
КонецПопытки;

Важный нюанс: при использовании этого метода необходимо следить за регистром и языком написания. Значение в квадратных скобках должно строго соответствовать имени идентификатора в платформе (например, только латиница "ANSI" или "OEM").

Способ 3. Автоматическое определение кодировки по заголовку файла (LDID)

Чтобы избавить пользователя от необходимости гадать, в какой кодировке сохранен файл, мы можем попытаться определить её программно. В спецификации формата 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;
    КонецЕсли;
    
КонецФункции

Способ 4. Эвристический анализ («поиск крякозябр»)

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

Проанализируем логику проверки:

  1. Откроем файл в режиме ANSI.
  2. Прочитаем значение любого текстового поля из первой записи.
  3. Проверим коды символов функцией КодСимвола().
  4. Если мы встречаем символы из диапазона псевдографики (например, коды 128–175), которые характерны для OEM (CP866), но в ANSI выглядят как странные значки — значит, файл в кодировке OEM.

Пример кода для частотного анализа:


Функция ЭтоКодировкаOEM(СтрокаДляПроверки)
    Для Поз = 1 По СтрДлина(СтрокаДляПроверки) Цикл
        Код = КодСимвола(СтрокаДляПроверки, Поз);
        // В CP866 русские буквы начинаются с 128
        // В Windows-1251 русские буквы начинаются с 192
        // Если видим много символов в диапазоне 128-175, скорее всего это OEM
        Если Код >= 128 И Код <= 175 Тогда
            Возврат Истина;
        КонецЕсли;
    КонецЦикла;
    Возврат Ложь;
КонецФункции

Важные рекомендации при работе с индексами

Разберем ситуацию, когда файл DBF сопровождается индексными файлами (.cdx или .ntx). Порядок сортировки строк в индексе напрямую зависит от кодировки. Если вы открываете файл в ANSI, а индексы были построены в OEM, поиск по индексу и методы Найти(), УстановитьФильтр() будут работать некорректно или возвращать пустые результаты.

Что нужно сделать:

  1. Всегда открывайте файл с правильной кодировкой до того, как задействуете индексы.
  2. Если вы программно меняете кодировку и планируете записывать данные, настоятельно рекомендуется выполнить метод Переиндексация(), чтобы избежать порчи индексных файлов.

Альтернативный подход через ADO

Если стандартный объект XBase не справляется (например, если файл поврежден или использует специфическую кодовую страницу, отличную от ANSI/OEM), можно использовать механизм ActiveX Data Objects (ADO). Этот метод позволяет более гибко настраивать параметры подключения через ConnectionString, указывая конкретного провайдера данных (например, Microsoft Jet 4.0 или Visual FoxPro Driver) и кодовую страницу.

Однако для большинства типовых задач в 1С объект XBase остается наиболее производительным и простым инструментом, если правильно управлять свойством Кодировка.

← На главную