Все было бы хорошо, если бы не BDE...
Нет, BDE - это очень даже хорошо, плохо то, что использовав в программе однажды
TTable, приходится ломать голову над тем, как же с минимальными потерями
"прикрутить" BorlandDatabaseEngine к пользовательской машине. Это первое, что
заставляет сесть за изучение заголовков DBF-файлов. И второе. Эти самые
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
- И многое, многое другое...
|