Шаг 22 - Скрипт и базы данных

Такое громкое название, как "База данных" зачастую скрывает в себе лишь один или несколько файлов, в которых хранятся в определенном формате данные. Каждый способен придумать свой формат файла базы данных, но в компьютерном мире уже существуют общепринятые форматы баз данных, которые понимают многие СУБД и программы. Одним из таких форматов является DBF (Data Base File). Наша задача проста: разобраться с форматом файлов DBF и написать соответствующую библиотеку классов для работы с ними. Я конечно понимаю, что это уже старо как мир и существует много готовых библиотек, но давайте напишем что-то сами для развития мозгов и своего навыка программирования.

Первым делом надо разобраться с форматом файлов DBF. На данном этапе я считаю важным разобраться только с форматом записи файла, а если быть точным, то с форматом описания структуры этой записи.

Вкратце и упрощенно о формате файла DBF. Сначала идет заголовок файла, с ним мы познакомимся чуть позже. Далее идет список полей в записи файла, т.е. имя, тип, длина соответствующего поля в записи. После этого списка идут подряд все записи файла, которые организуются по структуре описанной в списке полей.

Для полного описания поля записи используется структура длинной 32 байта, в которой:

0..10 байт - Название поля (11 байт).
11 байт - Тип поля.
12..15 байт - Позиция поля в записи (4 байта).
16 байт - Общая длина поля в байтах (вкл. плавающую точку).
17 байт - Длина дробной части вещественного числа.
18..31 байт - Зарезервировано (14 байт).

Давайте для хранения этой структуры создадим класс DBFRecordTypeField:

class DBFRecordType;//класс для структуры записи

class DBFRecordTypeField {
friend DBFRecordType;
	DBFRecordTypeField *Next, *Pred;//Переменные для списка
public:
	char Name[11]; //имя поля
	char Type; //тип поля
	long Position; //Позиция поля в записи
	unsigned char TotalLen;//Длина поля
	unsigned char DecimalLen;//Длина дробной части
	DBFRecordTypeField(char *name_,char type_, 
		unsigned char len_, unsigned char declen_);
	~DBFRecordTypeField();
};

Этот класс может в себе практически ничего не содержать кроме конструктора и деструктора:

DBFRecordTypeField::DBFRecordTypeField(char *name_,
	char type_, unsigned char len_, unsigned char declen_)
{
	int i=0;
	char b=0;

	for (i=0;i<11;i++){
		if ((*(name_+i)!=0)&&(b==0))
			Name[i]=*(name_+i);
		else {
			Name[i]=0;
			b=1;
		};
	};
	Type=type_;
	TotalLen=len_;
	if ((Type=='F')||(Type=='N')){
		DecimalLen=declen_;
	} else {
		DecimalLen=0;
	};
	if (Type=='L') TotalLen=1;
	Next=NULL;
	Pred=NULL;
};// DBFRecordTypeField;

Имя структуры заполняется слева направо и оставшиеся непонадобившиеся символы заполняются нулями. Переменную DecimalLen заполняем только в случае если поле вещественного или числового типа. А типы полей задаются символами соответствующих следующей табличке.

Тип поляЗначение
ЧисловоеN
ВещественноеF
СимвольноеC
ЛогическоеL
Типа MEMOM
ДатаD

Теперь осталось написать деструктор, который восстанавливает связи в нашем двусвязном списке. Почему двусвязном ? А просто так, мало ли что потом понадобится :-)

DBFRecordTypeField::~DBFRecordTypeField(){
	if (Pred!=NULL) Pred->Next=Next;
	if (Next!=NULL) Next->Pred=Pred;
};//~DBFRecordType;

Теперь есть элементарная "базовая ячейка", с помощью которой будем строить класс списка DBFRecordType, хранящего список полей записи.


Предыдущий Шаг | Следующий Шаг | Оглавление
Автор Кузин Андрей.