Читаем Фундаментальные алгоритмы и структуры данных в Delphi полностью

Метод Delete, прежде всего, проверяет, была ли удалена требуемая запись. Если запись была удалена, метод вызывает ошибку. Если все в порядке, текущее значение поля первой удаленной записи служебного заголовка копируется во флаг удаления записи. Затем значение поля первой удаленной записи устанавливается равным порядковому номеру удаляемой записи, количество активных записей в массиве уменьшается на единицу и обновляется служебный заголовок в потоке.

Метод Clear аналогичен Delete, но он предназначен для удаления всех активных записей постоянного массива.

Листинг 2.25. Очистка содержимого постоянного массива

procedure TtdRecordStream.Clear;

var

Inx : longint;

DeletedFlag : longint;

begin

{выполнить цикл по всем записям и объединить их в одну цепочку удаленных записей}

for Inx := 0 to pred(FCapacity) do

begin

rsSeekStream(rsCalcRecordOffset(Inx));

rsReadStream(DeletedFlag, sizeof(longint));

if (DeletedFlag = cActiveRecord) then begin

{записать порядковый номер первой удаленной записи в первые 4 байта удаляемой записи}

rsSeekStream(rsCalcRecordOffset(Inx));

rsWriteStream(FHeaderRec^.hr1stDelRec, sizeof(longint));

{обновить значение поля первой удаленной записи служебного заголовка, чтобы оно указывало на удаляемую запись}

FHeaderRec^.hr1stDelRec := Inx;

end;

end;

{записей нет}

FCount := 0;

FHeaderRec^.hrCount := 0;

{обновить служебный заголовок}

rsSeekStream(FZeroPosition);

rsWriteStream(FHeaderRec^, sizeof(TtdRSHeaderRec));

end;

Этот метод выполняет цикл по всем записям массива и, если запись активна, удаляет ее в соответствии с алгоритмом, используемым в методе Delete.

Класс TtdRecordStream позволяет также в один прием увеличивать емкость потока на несколько записей, а не добавлять записи по одной с помощью метода Add. Такая возможность позволяет зарезервировать место под постоянный массив, если заранее известно количество записей, которое будет в нем храниться. Запись свойства Capacity осуществляется через метод rsSetCapacity.

Листинг 2.26. Задание емкости постоянного массива

procedure TtdRecordStream.rsSetCapacity(aCapacity : longint);

var

Inx : longint;

begin

{допускается только увеличение емкости}

if (aCapacity > FCapacity) then begin

{заполнить текущую запись нулями}

FillChar(FRecord^, FRecordLen4, 0);

{найти конец файла}

rsSeekStream(rsCalcRecordOffset(FCapacity));

{создать дополнительные записи и внести их в цепочку удаленных записей}

for Inx := FCapacity to pred(aCapacity) do

begin

PLongint(FRecord)^ := FHeaderRec^.hr1stDelRec;

rsWriteStream(FRecord^, FRecordLen4);

FHeaderRec^.hr1stDelRec := Inx;

end;

{сохранить новую емкость}

FCapacity := aCapacity;

FHeaderRec^.hrCapacity := aCapacity;

{обновить служебный заголовок}

rsSeekStream(FZeroPosition);

rsWriteStream(FHeaderRec^, sizeof(TtdRSHeaderRec));

end;

end;

Как видно из приведенного кода, метод rsSetCapacity добавляет в конец потока пустые записи и вносит их в цепочку удаленных записей. После этого обновляются поля служебного заголовка, и в массиве появляется несколько удаленных записей, которые можно заполнить с помощью метода Add

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

Листинг 2.27. Низкоуровневые методы доступа к потоку

procedure TtdRecordStream.rsReadStream(var aBuffer;

a,BufLen : integer);

var

BytesRead : longint;

begin

BytesRead := FStream.Read(aBuffer, aBufLen);

if (BytesRead <> aBufLen) then

rsError(tdeRSReadError, 'rsReadStream', aBufLen);

end;

procedure TtdRecordStream.rsSeekStream(aOff set : longint);

var

NewOffset : longint;

begin

NewOffset := FStream.Seek(aOffset, soFromBeginning);

if (NewOffset <> aOffset) then

rsError(tdeRSSeekError, 'rsSeekStream', aOffset);

end;

procedure TtdRecordStream.rsWriteStream(var aBuffer;

aBufLen : integer);

var

BytesWritten : longint;

begin

BytesWritten := FStream.Write(aBuffer, aBufLen);

if (BytesWritten <> aBufLen) then

rsError(tdeRSWriteError, 'rsWriteStream', aBufLen);

Flush;

end;

Как видите, если результат выполнения одного из методов не соответствует ожидаемому, методы вызывают исключения.

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

Листинг 2.28. Реализация постоянных массивов с помощью файлового потока

constructor TtdRecordFile.Create(const aFileName : string;

aMode : word;

aRecordLength : integer);

begin

FStream := TFileStream.Create(aFileName, aMode);

inherited Create(FStream, aRecordLength);

FFileName := aFileName;

Mode := aMode;

end;

destructor TtdRecordFile.Destroy;

begin

inherited Destroy;

FStream.Free;

end;

procedure TtdRecordFile.Flush;

Перейти на страницу:

Похожие книги

1С: Бухгалтерия 8 с нуля
1С: Бухгалтерия 8 с нуля

Книга содержит полное описание приемов и методов работы с программой 1С:Бухгалтерия 8. Рассматривается автоматизация всех основных участков бухгалтерии: учет наличных и безналичных денежных средств, основных средств и НМА, прихода и расхода товарно-материальных ценностей, зарплаты, производства. Описано, как вводить исходные данные, заполнять справочники и каталоги, работать с первичными документами, проводить их по учету, формировать разнообразные отчеты, выводить данные на печать, настраивать программу и использовать ее сервисные функции. Каждый урок содержит подробное описание рассматриваемой темы с детальным разбором и иллюстрированием всех этапов.Для широкого круга пользователей.

Алексей Анатольевич Гладкий

Программирование, программы, базы данных / Программное обеспечение / Бухучет и аудит / Финансы и бизнес / Книги по IT / Словари и Энциклопедии
1С: Управление торговлей 8.2
1С: Управление торговлей 8.2

Современные торговые предприятия предлагают своим клиентам широчайший ассортимент товаров, который исчисляется тысячами и десятками тысяч наименований. Причем многие позиции могут реализовываться на разных условиях: предоплата, отсрочка платежи, скидка, наценка, объем партии, и т.д. Клиенты зачастую делятся на категории – VIP-клиент, обычный клиент, постоянный клиент, мелкооптовый клиент, и т.д. Товарные позиции могут комплектоваться и разукомплектовываться, многие товары подлежат обязательной сертификации и гигиеническим исследованиям, некондиционные позиции необходимо списывать, на складах периодически должна проводиться инвентаризация, каждая компания должна иметь свою маркетинговую политику и т.д., вообщем – современное торговое предприятие представляет живой организм, находящийся в постоянном движении.Очевидно, что вся эта кипучая деятельность требует автоматизации. Для решения этой задачи существуют специальные программные средства, и в этой книге мы познакомим вам с самым популярным продуктом, предназначенным для автоматизации деятельности торгового предприятия – «1С Управление торговлей», которое реализовано на новейшей технологической платформе версии 1С 8.2.

Алексей Анатольевич Гладкий

Финансы / Программирование, программы, базы данных