Александр Терехов дата публикации 17-07-2002 15:30 Структура DBF-файлов для непродвинутыхВступление
Все было бы хорошо, если бы не BDE...
Нет, BDE - это очень даже хорошо, плохо то, что использовав
в программе однажды TTable, приходится ломать голову над тем, как же с минимальными потерями
"прикрутить" BorlandDatabaseEngine к пользовательской машине. Это первое, что заставляет
сесть за изучение заголовков DBF-файлов. И второе. Эти самые DBF-файлы имеют такую особенность,
как разрушение заголовков. И третье, и четвертое, и пятое...
Для Вас не составляет сложности
написать компонент, который работает с DBF-таблицами?.
В этом случае НЕМЕДЛЕННО прекратите чтение статьи!
А мы же посмотрим, что из себя представляют заголовки DBF-файлов и как можно использовать
свои знания о них в практическом применении.
DBF-файл состоит из двух частей:
- заголовок
- собственно записи
Схематично все это можно представить так:
Таблица 1. Структура DBF-файла
Кол-во байт | Наименование |
32 |
Заголовок DBF-файла |
32 |
Описание первого поля |
32 |
Описание второго поля |
... |
... |
32 |
Описание n-го поля |
1 |
Завершающий символ 0x0D (13) |
RecordSize |
Первая запись из n-полей |
RecordSize |
Вторая запись из n-полей |
... |
... |
RecordSize |
m-я запись из n-полей, где m=RecordsCount |
1 |
Завершающий символ 0x1A (26) |
RecordSize
(размер записи в байтах)
и
RecordsCount
(количество записей), значения которых берутся
из заголовка DBF-файла, будут рассмотрены ниже.
Теперь, когда мы знаем из каких частей состоит DBF-файл и какой размер они имеют, перейдем
к более подробному рассмотрению их структуры.
Описание заголовка DBF-файла |
Как видно из предыдущей таблицы, заголовок состоит из трех частей:
- собственно заголовок
- описание полей
- завершающий заголовок символ 0x0D(13)
Размер "собственно заголовка" составляет 32 байта, каждый из которых несет строго
определенное значение.
Таблица 2. Структура DBF-заголовка
№ байта |
Размер |
Значение |
Описание |
Используется |
00 |
1 |
0x03(3) |
простая таблица |
FS, D3, D4, D5, Fb, Fp, CL |
0x04(4) |
простая таблица |
D4, D5 (FS) |
0x05(5) |
простая таблица |
D5, Fp (FS) |
0x43(67) |
с мемо-полем .dbv |
FS |
0xB3(179) |
с мемо-полями .dbv .dbt |
FS |
0x83(131) |
с мемо-полем .dbt |
FS, D3, D4, D5, Fb, Fp, CL |
0x8B(139) |
с мемо-полем .dbt формат D4 |
D4, D5 |
0x8E(142) |
SQL-таблица |
D4, D5 |
0xF5(245) |
с мемо полем .fmp |
Fp |
01 |
1 |
YY |
Год последнего обновления таблицы |
Все |
02 |
1 |
MM |
Месяц последнего обновления таблицы |
Все |
03 |
1 |
DD |
День последнего обновления таблицы |
Все |
04 |
4 |
RecordsCount |
Количество записей в таблице |
Все |
08 |
2 |
HeaderSize |
Размер заголовка в байтах |
Все |
10 |
2 |
RecordSize |
Размер записи в байтах |
Все |
12 |
2 |
0x00,0x00 |
Зарезервировано |
Все |
14 |
1 |
0x01 |
Начало транзакции |
D4, D5 |
0x00 |
Конец транзакции |
D4, D5 |
0x00 |
Игнорируется |
FS, D3, Fb, Fp, CL |
15 |
1 |
0x01 |
Закодировано |
D4, D5 |
0x00 |
Нормальная видимость |
Все |
16 |
12 |
0 (1) |
Использование многопользовательского окружения |
D4, D5 |
28 |
1 |
0x01 |
Используется индекс |
Fp, D4, D5 |
0x00 |
Индекс не используется |
Все |
29 |
1 |
n |
Номер драйвера языка |
D4, D5 |
0x01(1) |
кодовая страница 437 DOS USA |
Fp |
0x02(2) |
кодовая страница 850 DOS Multilang |
Fp |
0x26(38) |
кодовая страница 866 DOS Russian |
Fp |
0x57(87) |
кодовая страница 1251 Windows ANSI |
Fp |
0xC8(200) |
кодовая страница 1250 Windows EE |
Fp |
0x00(0) |
игнорируется |
FS, D3, Fb, Fp, CL |
30 |
2 |
0x00,0x00 |
Зарезервировано |
Все |
Сокращения:
- FS = FlagShip
- Fb = FoxBase
- Fp = FoxPro
- CL = Clipper
- D3 = dBaseIII+
- D4 = dBaseIV
- D5 = dBaseV
Таким образом мы сумели описать первых 32 байта DBF-файла. Начиная с 33 байта начинаются
описания полей, каждое из которых также имеет размер в 32 байта.
Структура описания полей в заголовке DBF-файла |
Таблица 3. Структура описания полей в заголовке DBF-файла
№ байта |
Размер |
Значение |
Описание |
Используется |
00 |
11 |
ASCII |
Имя поля с 0x00 завершением |
Все |
11 |
1 |
ASCII |
Тип поля
см. Таблицу 4 |
Все |
12 |
4 |
n,n,n,n |
Адрес поля в памяти |
D3 |
0,0,n,n |
Смещение относительно начала записи |
Fp |
0,0,0,0 |
Игнорируется |
FS, D4, D5, Fb, CL |
16 |
1 |
Byte |
Размер поля
см. Таблицу 4 |
Все |
17 |
1 |
Byte |
Количество знаков после запятой |
Все |
18 |
2 |
0,0 |
Зарезервировано |
Все |
20 |
1 |
Byte |
Идентификатор рабочей области |
D4,D5 |
0x00 |
Не используется |
FS, D3, Fb, Fp, CL |
21 |
2 |
n,n |
Многопользовательский dBase |
D3, D4, D5 |
0,0 |
Игнорируется |
FS Fb, Fp, CL |
23 |
1 |
0x01 |
Установленные поля |
D3, D4, D5 |
0x00 |
Игнорируется |
FS Fb, Fp, CL |
24 |
7 |
0..0 |
Зарезервировано |
Все |
31 |
1 |
0x01 |
Поле включено в .mdx индекс |
D4, D5 |
0x00 |
Игнорируется |
D3, FS, Fb, Fp, CL |
Таблица 4. Типы полей и их размеры
Код |
Тип |
Размер |
Описание/Размер |
Используется |
C |
1..n |
Char |
n ASCII символов |
Все |
пустые места - пробел 0x20(32) |
n = 1..64Kbt |
FS |
n = 1..32Kbt |
Fp, CL |
n = 1..254 |
Все |
D |
8 |
Date |
8 ASCII знаков (0..9) в формате YYYYMMDD |
Все |
F |
1..n |
Float |
ASCII символы(-.0123456789) переменная позиция плавающей точки
n = 1..20 |
FS, D4, D5, Fp |
N |
1..n |
Numeric |
ASCII символы (-.0123456789) фиксированная позиция точки |
Все |
n = 1..20 |
FS, Fp, CL |
n = 1..18 |
D3, D4, D5, Fb |
L |
1 |
Logical |
ASCII символы (Yy Tt Nn Ff, пробел - не определено) |
FS, D3, Fb, Fp, CL |
ASCII символы (Yy Tt Nn Ff, ? - не определено) |
D4, D5 (FS) |
M |
10 |
Memo |
10 цифр, определяющих начало блока данных в .dbt-файле
или 10 пробелов, если поле мемо пусто |
Все |
V |
10 |
Variable |
Переменная Bin/ASCII данных в .dbv-файле
4 Bin байтов - начало блока в мемо-файле
4 Bin байтов - размер блока
1 Bin байт - подтип данных
1 Bin байт - зарезервировано 0x1A(26) |
FS |
P |
10 |
Picture |
Binary данные в .ftp-файле
структура такая же как и в Memo-типе |
Fp |
B |
10 |
Binary |
Binary данные в .dpt-файле
структура такая же как и в Memo-типе |
D5 |
G |
10 |
General |
OLE-объекты
структура такая же как и в Memo-типе |
D5, Fp |
2 |
2 |
short int |
Binary int max +/- 32767 |
FS |
4 |
4 |
long int |
Binary int max +/- 2147483647 |
FS |
8 |
8 |
double |
Binary signed double IEEE |
FS |
Завершает описание заголовка символ 0x0D(13)
Теперь уже можно сделать кое-какие вычисления. Например,
определить количество полей в DBF-файле.
Размер заголовка DBF-файла в байтах составляет:
32+32xN+1 байт, где N - количество полей.
Этот же размер можно извлечь из 8,9 байтов заголовка -
HeaderSize
Следовательно количество полей равно:
N:=(HeaderSize-33)/32 байт.
Сместившись на HeaderSize байт от начала файла, мы переходим к
непосредственно к самим записям,
размер которых указан в 10,11 байтах заголовка -
RecordSize, а их количество
в 04..07 байтах -
RecordsCount.
Структура записи в DBF-файле более простая.
Структура записи в DBF-файле |
Каждая запись имеет следующую структуру.
Таблица 5. Структура записи в DBF-файле
№ байта |
Размер |
Описание |
Используется |
0 |
1 |
Флаг удаления "*", иначе - пробел |
Все |
1 |
1..n |
Различные типы полей фиксированной длины
без завершающих символов
длина поля n определяется в 16 байте структуры описания поля. |
Все |
Завершает DBF-файл символ 0x1A(26)
Таким образом, в общем случае запись - это строка символов (кроме FS), состоящая из
частей (полей) строго определенного размера. Эти размеры указаны в структуре
описания поля в 16-м байте.
Теперь, изучив строение структуры DBF-файла мы можем:
- Получить важные сведения о DBF-файле из его первых 32 байтов
- Изменить несколько важных значений DBF-файла:
- изменить языковой драйвер таблицы
- отвязать таблицу от индексного файла
- по желанию - еще что-нибудь
- Определить количество и тип полей в DBF-файле
- Отследить разрушение заголовка DBF-файла путем расчета места нахождения завершающего
заголовок символа и сравнения его с 0x0D(13)
- Попытаться восстановить заголовок
- Создать примитивный драйвер работы с DBF-файлом без BDE
- И многое, многое другое...
Небольшой пример
Пример примитивного драйвера работы с DBF-файлом без BDE и возможности изменения заголовка
DBF-файла находится в файле
DBHeader.zip (7K)
Пример подробно откомментирован, поэтому в тексте статьи приводить его не буду. Тем более что,
как говорится, "лучше один раз увидеть"...
В качестве полигона можно использовать DBF-таблицы, поставляемые вместе с Delphi:
\DelphiX\Demos\Data\*.dbf
В дополнение к материалу: DBFCodePage.zip (1.7K) небольшой
перекодировщик (языковой драйвер) ascii ANSI Win 1251 в dBase
RUS cp866 и обратно.
© Терехов Александр
[DBase] [Прямой доступ к БД]
Обсуждение материала [ 11-04-2012 12:38 ] 17 сообщений |