logo
Подбельский Фомин_Программирование на языке СИ_

Сохранение (восстановление) базы данных.

Сохранение (восстановление) базы данных. Поскольку в рассматриваемом примере база данных реализована в виде двунаправленного списка в основной памяти и она стирается (ее содержимое исчезает) при завершении работы программы, необходимо предусмотреть как сохранение базы данных во внешней памяти, так и загрузку базы данных из внешней памяти в следующем сеансе работы с ней.

Перед разработкой функции "выгрузка" базы данных в файл на диске необходимо определить формат и состав выгружаемых данных.

Собственно база данных (в виде двух независимых двунаправленных списков - списка занятых элементов и списка свободных элементов) располагается в массиве st структур типа struct person (см. главную программу). Информация о количестве элементов в этих списках, а также указатели на начало и конец списков располагаются в структуре Ctrl типа struct control.

Рассмотрим один из простейших вариантов создания на диске резервной копии базы данных о сотрудниках учреждения. Он состоит в том, что сначала необходимо записать в файл управляющую информацию (содержимое структуры Ctrl), а за ней - весь массив структур (байт за байтом), тем более что в рассматриваемом примере он невелик (7 Кбайт). При восстановлении базы данных из файла на диске читается управляющая информация и размещается в структуре Ctrl, затем читается информация, расположенная в файле за управляющей информацией, и размещается в области основной памяти, отведенной под массив структур st.

Такая схема копирования (восстановления) обладает существенным недостатком: вместе с содержательной информацией в файл записываются и значения указателей (адреса основной памяти), содержащиеся в элементах списков базы данных. Таким образом, при принятой схеме копирования (восстановления) программа обслуживания базы данных будет работать при выполнении условия неизменности адреса загрузки программы в основную память. При работе на персональном компьютере в операционных системах MS-DOS и UNIX (однопользовательский режим) вызванная для выполнения программа будет загружена на то же самое место в основной памяти только в том случае, если между сеансами работы с программой не производились "системные" работы, повлекшие за собой перераспределение основной памяти.

Однако, несмотря на неполную надежность восстановления, приведем исходные тексты функций save( ) - "выгрузить базу данных в файл на диске" и load( ) - "восстановить базу данных из файла". В этих функциях показано, как можно выгрузить (и затем восстановить) из основной памяти в файл на диске содержимое переменных различных типов.

Операция sizeof, примененная в функциях save( ) и load( ), вычисляет длину операнда в байтах. Операторы с = (char *)pti; и с = (char *)ptr; производят явное преобразование указателя pti на целое и указателя ptr на структуру соответственно в указатели на символы, что позволяет использовать последние в качестве аргументов в функциях putc( ) и getc( ) для побайтного обмена с файлом.

В функции save( ) производится запись в файл на диске всех элементов массива структур. Запись производится функцией putc( ) побайтно. Поэтому в программе необходимо описать указатель на символы, т.е. типа char*. Для работы с массивом структур необходим указатель на структуру типа person, содержащую сведения о сотруднике учреждения, и указатель потока, связанный с файлом, в котором производится сохранение базы данных. Назовем этот файл bd.dat.

Приведем текст функции save( ):

Функция load( ) может быть реализована следующим образом:

Перед восстановлением базы данных с диска проверяют, пуст ли список занятых элементов в основной памяти. Если нет, то выдается запрос "Производить загрузку?". В случае неположительного ответа, обозначаемого латинской буквой N или n, загрузка информации в БД из файла не производится.

Для того чтобы программа обслуживания базы данных стала не зависимой от адреса загрузки в основную память, модернизируем функции save() и load() следующим образом:

• будем выгружать (записывать) в файл не весь массив структур, а только список занятых элементов;

• после чтения содержимого файла в массив структур скорректируем значения указателей, образующих связи в связных списках базы данных, т.е. установим реальные адреса в указателях.

На рис. 8.10 показаны состояние списка занятых элементов в массиве структур до выгрузки в файл, структура файла с информацией из базы и состояние массива структур после восстановления базы данных из файла. В общем случае элементы списка, содержащего сведения о сотрудниках, к концу сеанса работы с базой данных могут располагаться не в соседних элементах массива. Однако после выгрузки в файл эти элементы окажутся рядом. Читая из файла в массив структур список занятых элементов байт за байтом, мы размещаем элементы списка с начала массива структур, т.е. элементы списка, в котором хранятся сведения о сотрудниках, в общем случае попадают на новые места в массиве структур, и требуется корректировка адресов в элементах этого списка. Эта процедура аналогична процедуре инициализации массива структур перед началом работы с базой данных. Началом списка свободных элементов будет первый элемент массива структур, не занятый загруженной из файла информацией.

Рис. 8.10. Второй вариант схемы сохранения (восстановления) базы данных

Приведем текст функции save2( ) - "сохранить в файле на диске только список занятых элементов":

Приведем текст функции load2( ) - "загрузить в основную память (прочитать из файла) базу данных из файла с корректировкой адресов, содержащихся в указателях элементов списков базы данных".

В качестве упражнения рекомендуем разработать более надежную схему и формат хранения базы данных и соответствующие функции сохранения (восстановления). В качестве возможного варианта формата хранения базы данных в файле на диске можно использовать следующий:

#1

name=фамилия

dерnаmе=название_отдела

depnumb=код_отдела

price=зарплата

job=код_должности

joname=долукиость

date=дата_приема_на_работу

#2

name=фамшия

где

#1, #2,... - номера записей;

name=, depname=, ... - имена полей в структуре, содержащей сведения о сотрудниках учреждения;

фамилия, название_отдела, ... - содержимое полей структуры в символьном виде.

Файл в таком формате и символьном представлении значений полей структур легко прочитать и модифицировать с помощью любого текстового редактора. Имена полей можно использовать для контроля правильности обработки записи при вводе (см. гл. 7, форматный ввод). Список занятых элементов базы данных формируется в момент ввода данных из файла.

Для того чтобы подготовить программный комплекс к последующей обработке (трансляция, сборка), в простейшем случае необходимо с помощью текстового редактора собрать все функции в один файл (набор данных). Этот файл должен иметь следующую структуру:

• объектов, используемых во вспомогательных функциях (массив структур типа struct person, управляющие переменные в структуре ctrl);

• описание внешних переменных;

• функция main( );

• функция init( );

• функция find( );

• функция fr( );

• функция delete( );

• функция input( );

• функция print( );

• функция save( ) или функция save2( );

• функция load( ) или функция load2( ).

Подробно подготовка программного комплекса для работы с базой данных о сотрудниках учреждения описана в главе 9.