Библиотека для работы с dbf-файлами под ДОС.
by S.Kasandrov, 1993,95. public domain.
Краткое описание
1. Я пользуюсь этой библиотекой более года, однако
в представленом виде ( модули Lib+Files) она еще никогда не
существовала. При подготовке окончательной редакции из модуля
Files пришлось выбросить все, что завязано с пользовательским
интерфейсом - иначе я никогда не смог бы завершить работу.
По этой причине некоторые вещи стали выглядеть коряво - об этом
в п. 3.
2. За основу при разработке методов работы с dbf-файлами
был взят командный язык FoxPro. Синтаксис многих методов DBaseFile
и функций Lib очень похож на синтаксис соответствующих команд и
функций XBase-систем, однако есть несколько смысловых различий:
- метод Zap не только сбрасывает в ноль счетчик числа записей
в заголовке файла, но и выполняет физическое усечение файла;
- соответствие размера файла числу записей, указанному в заголовке,
используется как сигнатура dbf-файла;
- методы Scatter и Gather используются для прямого выталкивания
записей dbf-файла c диска (на диск).
Изначально модуль был ориентирован на монопольную работу c файлами
с не очень больших размеров ( до нескольких MByte). Для таких задач
хорошее быстродействие достигалось за счет блочной буферизации обмена
с диском по чтению и записи c использованием одного буфера. Второй
блочный буфер появился при разработке процедуры сортировки с целью
исключения ситуаций, когда запись находится частично на диске, а
частично в буфере, и именно использование второго блочного буфера
обеспечило хорошую скорость сортировки.
Когда из блочной буферизации было выжато все, я решил включить в
модуль средства поддержки одновременной сетевой работы нескольких
пользователей и пришел к следующим выводам:
- копировать XBase-технологию с ее чтением/записью записей -
значит расстаться с высоким быстродействием;
- при разделенной работе блочная запись становится недопустимой,
однако нет причин, по которым нельзя пользоваться блочным чтением.
В результате средства поддержки сетевой работы не отменяют
блочную буферизацию, а дополняют ее следующим уровнем - буферизацией
логических записей. Буферов логических записей также 2, второй
используется для хранения копии записи в процессе редактирования
для отмены результатов редактирования и проверки внесения
изменений при редактировании.
В целом поддержка сетевой работы только намечена, однако
я не вижу здесь каких-то больших трудностей - просто у меня нет
таких задач.
3. Советы на будущее:
- Допишите функцию ErrorChecked - у меня она при CheckError=True
и DosError<>0 выбрасывает окошко с сообщением об источнике ошибки
( параметр функции), коде ошибки (DosError), расширенном коде
( GetErrCode) и меню из 2 блюд - повторить операцию ( поэтому
все методы BinFile в цикле) или отказаться. Во втором случае
при установленном DosBreak должна вызываться процедура аварийного
завершения( вместо Halt).
- Cтандартная процедура аварийного завершения должна попытаться
закрыть все файлы, поэтому неплохо сделать регистрацию открываемых
файлов - у меня пока руки не дошли.
- Подумайте, что делать при переполнении диска
(procedure DiskOverflow - у меня просто выбрасывает окошко с
сообщением о переполнении, ждет нажатия клавиши и делает Halt).
4. Некоторые методы DBaseFile:
procedure Open( FileName: String; Size: Word);
Открывает DBaseFile,
Size - размер блочного буфера в байтах, их два, поэтому
в куче резервируется 2*Size байт.
procedure Flush; - сбрасывает все ( в том числе внутренние
буфера DOS ) на диск, корректирует( если надо) длину файла
в элементе каталога.
procedure Truncate; - отсекает все записи начиная с текущей
procedure Remove; - физически удаляет текущую запись
procedure Zap; - физически удаляет все записи
procedure Pack; - упаковка ( физическое удаление меченых ('*') записей)
{ Установка номера текущей записи }
procedure GoTop;
procedure GoBottom;
procedure Go( N: LongInt);
procedure Skip( N: LongInt);
procedure AppendBlank; - корректное добавление пустой записи
в DBF-файл, т.е. все буфера сбрасываются на диск и корректируется
длина файла в элементе каталога.
procedure Append; - корректное добавление записи из Buf_1
function DelCount: LongInt; { Подсчет числа меченых записей }
function FastStore( Ident: FieldName): String; -
чтение поля через блочный буфер;
function Store( Ident: FieldName): String; -
чтение поля из Buf_1;
procedure FastReplace( Ident: FieldName; Source: String); -
запись поля через блочный буфер;
procedure Replace( Ident: FieldName; Source: String); -
запись поля в Buf_1;
procedure BubbleSort( Ident: FieldName); - сортировка по полю,
основательно переработанная на предмет оптимизации идея
пузырьковой сортировки;
procedure Gather; - прямая запись из Buf_1 на диск;
procedure Scatter; - прямое чтение с диска в Buf_1.
5. Буду благодарен за найденные глюки и дельные идеи
по развитию библиотеки.
|