Параметризованные файлы записей фиксированной длины
В файле, записи которого имеют фиксированную размерность, очень просто вычислять их смещение (адрес, позицию). Структуру такого файла можно усложнить, если сделать размерность записей зависимой от параметров, которые также можно хранить в том же файле, но "ближе к началу". Тогда можно получить структуру данных с варьируемой от файла к файлу размерностью. Работа с таким файлом происходит по принципу "раскрутки": читаются параметры, определяющие размерность следующей компоненты, в которой находятся новые параметры и т.д.. В качестве примера приведем фрагмент программы, работающей с файлом-таблицей с произвольным количеством и типами столбцов. Файл содержит целые переменные -количество столбцов и строк, затем соответствующее количество структурированных переменных -описателей столбцов, а затем сами строки таблицы.
//------------------------------------------------------bk59-02.cpp
// Параметризованный файл записей фиксированной длины
#include <stdio.h>
#include <alloc.h>
struct item // Описатель столбца
{
int type; // тип столбца
int size; // размерность столбца
char name[30]; // Имя столбца
};
struct TableDef // Описатель таблицы
{
FILE *fd; // Дескриптор файла
int ns; // Количество столбцов
int nr; // Количество строк
int strlnt; // Размер строки таблицы
int size0; // Смещение строк таблицы в файле
item *ST; // Динамический массив описателей
};
//------ Открыть файл и прочитать описатели столбцов -----
TableDef *OpenTable(char *name)
{ int i; // Ниже для простоты
TableDef *p; // отсутствуют многочисленные
p= new TableDef; // проверки результата функции
if ((p->fd = fopen(name,"rb+wb"))==NULL)
{ delete p; return NULL; } // Открыть файл
fread( (void*) &p->ns,sizeof(int),1,p->fd); // Чтение ns
fread( (void)&p->nr,sizeof(int),1,p->fd); // Чтение nr
p->ST= new item[p->ns];
fread(p->ST,sizeof(item),p->ns,p->fd); // Чтение массива описателей
// Определение size0
p->size0=sizeof(int)*2 + sizeof(item) * p->ns;
for (i=0,p->strlnt=0; i<p->ns; i++) // Определение длины
p->strlnt += p->ST[i].size; // строки таблицы
return(p);
}
//----- Чтение элемента таблицы из столбца j строки i
// функция возвращает элемент в динамической памяти
void *getrec(int i, int j, TableDef *p)
{
void *data;
int lnt; // Суммарная размерность
int k; // столбцов от 0 до j-1
if (p->fd ==NULL) return NULL;
if (p->ns <=j || p->nr <=i) return NULL;
for (k=0,lnt=0; k<j; k++) lnt += p->ST[k].size;
data = malloc(p->ST[j].size);
fseek(p->fd, p->size0 + (long)p->strlnt*i + lnt, 0);
//
// Смещение строк таблицы в файле +
// Размерность i полных строк +
// Сумма длин столбцов от 0 до j-1
//
fread(data,p->ST[j].size,1,p->fd);
return data;
}