Кракозябры в DBF: как понять, какая нужна кодировка
В DBF нет метки «этот файл в UTF-8». Кодировка либо указана одним байтом в заголовке, либо не указана вовсе — и тогда её приходится определять по содержимому. Отсюда и берутся «╨╬╤╤╚╧» вместо «РОССИЯ».
Откуда берётся проблема
DBF — формат однобайтовый: каждый символ занимает ровно один байт. Какой именно букве соответствует байт 0xC0, зависит от кодовой таблицы. В cp866 (DOS) это «А», в windows-1251 — тоже «А», а вот байт 0xA0 в cp866 даёт «а», а в windows-1251 — неразрывный пробел.
Программа, которая писала файл, знала свою таблицу. Программа, которая его читает, обязана эту таблицу угадать — либо взять из заголовка.
Языковой драйвер: байт 29 заголовка
В заголовке DBF на 29-м байте (считая с нуля) лежит Language Driver ID — код кодовой страницы. Самые частые значения в наших краях:
| Код | Кодировка | Откуда такие файлы |
|---|---|---|
0x26, 0x65 | cp866 | Clipper, FoxPro 2.x, DOS-программы |
0xC9 | windows-1251 | Visual FoxPro, выгрузки 1С |
0x03, 0x57 | windows-1252 | западные программы |
0x00 | не указана | примерно половина файлов в реальной жизни |
Беда в том, что байт может и врать: файл создали одной программой, дописали другой, а заголовок остался прежним. Поэтому верить ему безоговорочно нельзя.
Как отличить cp866 от windows-1251 глазами
Есть два надёжных признака.
Псевдографика
Если текст пестрит символами рамок — ╬ ╤ ╚ ╧ ╨ ╟ — значит, файл в windows-1251, а читают его как cp866. В DOS-кодировке верхняя половина таблицы занята псевдографикой, и русские буквы попадают именно туда.
Заглавные буквы посреди слова
Если вместо «Иванов» получается «хБЮМНБ» — буквы русские, но регистры скачут внутри слова, — перепутаны cp1251 и KOI8-R. В KOI8-R буквы расставлены так, что при неверном чтении строчные и прописные меняются местами.
Именно на этом признаке построено автоопределение в TablesViewer: текст декодируется каждой кодировкой-кандидатом, и та, где заглавные буквы не лезут в середину слов, а частотность букв похожа на русскую речь, выигрывает.
Что делать на практике
- Откройте файл и посмотрите на текстовые поля. Если читается — всё в порядке, кодировка определилась.
- Видите псевдографику — переключите на windows-1251. Видите «хБЮМНБ» — тоже windows-1251.
- Переключение кодировки не требует повторного открытия: файл не перечитывается, меняется только таблица перевода байтов в символы.
- Если часть полей читается, а часть нет — скорее всего, в одном файле смешаны данные из разных источников. Такое чинится только на стороне того, кто файл формировал.
Отдельная тонкость: имена полей тоже бывают кириллическими и тоже перекодируются. Если в шапке таблицы каша, а в данных нет — вы смотрите на файл, где имена писали в одной кодировке, а данные в другой.
Почему не «просто UTF-8»
Соблазн пересохранить всё в UTF-8 понятен, но DBF этого не умеет: длина поля в заголовке задана в байтах, а кириллица в UTF-8 занимает два байта на символ. Поле C(20) вместит двадцать латинских букв и только десять русских — остальное молча обрежется.
Поэтому при выгрузке обратно в DBF кодировка всегда однобайтовая, а длины полей пересчитываются по фактическим данным в целевой кодировке.
Частые вопросы
Можно ли узнать кодировку, не открывая файл?
Посмотрите байт со смещением 29 в шестнадцатеричном редакторе. Но помните, что он часто равен нулю или содержит неверное значение — содержимое надёжнее.
Почему в одной программе файл читается, а в другой нет?
Разные программы по-разному поступают при отсутствии языкового драйвера: одна берёт системную кодировку Windows, другая — cp866 по умолчанию. Файл при этом одинаковый.
Испортится ли файл, если я переключу кодировку в просмотрщике?
Нет. Переключение влияет только на отображение: байты в файле не меняются, пока вы явно не сохраните правки.