Ударим классом по двоичному файлу
Для начала выполним чисто косметические действия: оформим в виде отдельного класса файловый поток ввода вывода (fstream) в режиме работы с двоичным файлом произвольного доступа.
//------------------------------------------------------bk8-01.cpp
#include <fstream.h>
#define FNULL -1L
typedef int BOOL;
typedef long FPTR; // Тип - указатель в файле
typedef unsigned char _FAR *BUF; // Тип - указатель буфера
// файла в stdio
class TElem;
class BinFile : public fstream
{
public:
BOOL Create(char *); // Создать пустой файл
BOOL Open(char *); // Открыть существующий
FPTR Size() // Получить длину файла и
{ seekg(0L,ios::end); // позиционироваться на
return(tellg()); } // конец файла
void *VSZLoad(int&); // Функции для работы с
FPTR VSZAppend(void*,int); // записями переменной
FPTR VSZUpdate(void*,int,int); // длины
BinFile() { fstream(); } //
~BinFile(){ close();} //
};
BOOL BinFile::Create(char *s)
{
int a=1;
open(s, ios::trunc | ios::out | ios::binary );
if (good()) { close(); return(1); }
return(0);
}
BOOL BinFile::Open(char * s)
{
open(s,ios::in | ios::out | ios::binary);
return(good());
}
// До сих пор функции-элементы класса представляли
// собой практически чистые вызовы библиотечных функций.
// Но поскольку значительное число объектов имеет переменную
// размерность, то класс BinFile полезно дополнить функциями,
// работающими с записями переменной длины. Напомним, что
// запись переменной длины в файле представлена целой пере-
// менной - счетчиком и следующими за ними байтами данных,
// число которых определяется счетчиком. */
//------ При загрузке записи переменной длины память
// под нее выделяется в виде динамического массива
void *BinFile::VSZLoad(int &sz)
{
char *pdata;
read((BUF)&sz, sizeof(int));
if (!good()) return(NULL);
if ((pdata = new char[sz])==NULL ) return(NULL);
read((unsigned char *)pdata,sz);
if (good()) return((void *)pdata);
delete pdata;
return(NULL);
}
//----- При выводе записи переменной длины на место уже
// существующей проверяется размерность старой записи.
// Если она недостаточна, новая запись добавляется в конец
// файла. Значение параметра mode=1 устанавливает режим
// проверки.
FPTR BinFile::VSZUpdate(void *buf ,int sz, int mode)
{
int oldsz;
FPTR pos;
pos = tellg();
if (mode)
{
read((BUF)&oldsz,sizeof(int));
if (!good()) return(FNULL);
if (oldsz < sz) return(VSZAppend(buf,sz));
seekg(pos);
if (!good()) return(FNULL);
}
write((BUF)&sz,sizeof(int));
write((BUF)buf,sz);
if (!good()) return(FNULL);
return(pos);
}
FPTR BinFile::VSZAppend(void *buf ,int sz)
{
FPTR pos;
if ((pos = Size()) ==FNULL) return(FNULL);
write((BUF)&sz,sizeof(int));
write((BUF)buf,sz);
if (!good()) return(FNULL);
return(pos);
}