📄 数据库算法(一)代码列表.c
字号:
数据库算法(一)代码列表
列表2:TaaRecordStream类的接口
type
PaaRSHeaderRec = ^TaaRSHeaderRec;
TaaRSHeaderRec = packed record
hrSignature : longint;
hrHeaderLen : longint;
hrRecorderLen : longint;
hrCount : longint; { the number of active records }
hrCapacity : longint; { the number of all records }
hr1stDelRec : longint;
end;
type
TaaRecordStream = class
private
FFileStrm : TFileStream;
FHeader : PaaRSHeaderRec;
FStream : TSream;
FRecLen : integer;
protected
procedure rsCreateNew;
procedure rsOpenExisting;
function rsCalcRecordOffset( aRecNum : integer ) : longint;
procedure rsReadStream( var aRec ; aRecLen : integer );
procedure rsSeekStream( aOffset : longint );
procedure rsWriteStream( const aRec ; aRecLen : integer );
public
constructor Create( aStream : TStream; aCreateNew : boolean ;
aRecLen : integer );
constructor CreateFile( const aFileName : string ; aCreateNew : boolean ;
aRecLen : integer );
destructor Destroy : override;
function Add( const aRec ) : integer;
procedure Delete( aRecNum : integer );
function Read( aRecNum : integer : var aRec ) : Boolean;
procedure Write( aRecNum : integer ; var aRec );
end;
列表3:TaaRecordStream类的实现
const
cRSSignature = $1A524454;
cActiveRecord = -2;
cEndOfDeletedChain = -1;
constructor TaaRecordStream.Create( aStream : TSream ;
aCreateNew : boolean; aRecLen : integer );
begin
{create the ancestor}
inherited Create;
{save the parameters}
FStream := aStream;
FRecLen := aRecLen;
{if we should create a new record stream . do so}
if aCreateNew then begin
Assert(aRecLen > 0 , 'TaaRecordStream.Create: ' +
'the record length must be greater than zero' );
rsCreateNew;
end else
esOpenExisting;
end;
constructor TaarecordStream.CreateFile( const aFileName:string;
aCreateNew : boolean; aRecLen : integer );
begin
{if needed , create the file}
if aCreateNew then begin
FFileStrm := TFileStream.Create( aFileName , fmCreate );
FFileStrm.Free;
FFileStrm := nil;
end;
{create the file stream}
FFileStrm := TFileStream.Create( aFileName ,
fmOpenReadWrite + fmShareDenyWrite );
{call the other construcor to finish off}
Create(FFileStrm , aCreateNew , aRecLen );
end;
destructor TaaRecordStream.Destroy;
begin
{if we created a file stream , close it}
if( FFileStrm <> nil ) then
FFileStrm.Free;
{frre the header record}
if( FHeader <> nil ) then
FrreMem( FHeader , Fheader^.hrHeaderLen );
{finally destroy the ancestor}
inherited Destroy;
end;
function TaaRecordStream.Add( const aRec ) : integer;
var
TempRec : PChar;
Offset : longint;
begin
{if the deleted record chain is empty , we'll be adding the
record to the end of the stream; calculate its offset}
if (FHeader^.hrstDelRec = cEndOfDeletedChain ) then begin
Result := FHeader^.hrCapacity;
inc(FHeader^.hrCapacity);
Offset := rsCalcRecordOffset(Result);
end else begin
{otherwise , use the first deleted record , upsate the
header record's deleted record chain to start at
the next deleted record}
Result := FHeader^.hr1stDelREc;
Offset := rsCalcRecordOffset(Result);
rsSeekStream(Offset);
rsReadStream(FHeader^.hr1stDelRec , sizeof(longint));
end;
{seek to the record offset and write the new record}
rsSeekStream(Offset);
GetMem( TempRec , FRecLen + sizeof(longint));
try
PLongint(TempRec)^ := cActiveRecord;
Move(aRec , TempRec[sizeof(longint)],FRecLen);
rsWriteStream(TempRec^,FRecLen + sizeof(longint));
finally
FreeMen(TempRec , FRecLen + sizeof(longint));
end;
{we have one more active record}
inc(FHeader^.hrCount);
{now update the header record}
rsSeekStream(0);
rsWriteStream(FHeader^.sizeof(TaaRSHeaderRec));
end;
procedure TaaRecordStream.Delete(aRecNum : integer);
var
DelLink : longint;
Offset : longint;
begin
{calculate the record offset}
Offset := rsCalcRecordOffset(aRecNum);
{check to see that the record is not already deleted}
rsSeekStream(Offset);
rsReadStream(DelLink,sizeof(longint));
if (DelLink <> cActiveRecord) then
raise Exception.Create(
'TaaRecordStream.Delete record already deleted');
{write the first deleted record number to the first 4 bytes of the
record we're deleting}
rsSeekStream(Offset);
rsWriteStream(FHeader^.hr1stDelRec , sizeof(longint));
{update the deleted record chain to start at the record we're
deleting}
FHeader^.hr1stDelRec := aRecNum;
{we have one less record}
dec(FHeader^.hrCount);
{now update the header record}
rsSeekStream(0);
rsWriteStream(FHeader^,sizeof(TaaRSHeaderRec));
end;
function TaaRecordStream.Read(aRecNum : integer; var aRec):boolean;
var
TempRec : PChar;
Action : integer;
Offset : longint;
begin
{calculate the record offset}
offset := rsCalcRecordOffset(aRecNum);
{get a temporary buffer in order to read entire record}
ActLen := FRecLen + sizeof(longint);
GetMem( TempRec , ActLen );
try
{seek and read the entire record}
rsSeekStream(Offset);
rsReadStream(TempRec^ , ActLen);
{if it's deleted , return flase}
if (PLongint(TempRed)^ <> cActiveRecord ) then
result := false;
{otherwise transfer the record data}
else begin
Result := true;
Move(TempRec[sizeof(longint)] , aRec , FRecLen );
end;
{finally free our temporary buffer}
finally
FreeMem(TempRec , ActLEn);
end;
end;
function TaaRecordStream.rsCalcRecordOffset( aRecNum : integer ):longint;
begin
{first verify that the record number is in range}
if (aRecNum < 0) or (aRecNum > FHeader^.hrCapacity) then
raise Exception.Create('TaaRecordStream.rsCalcRecordOffset :'
+ 'record number is out of range' );
{second ,calculate the offset}
Result := FHeader^.hrHeaderLen + (aRecNum*(FRecLen + sizeof(longint)));
end;
procedure TaaRecordStream.rsCreateNew;
var
HeaderSize : integer;
begin
{calculate the size of the header}
HeaderSize := FRecLen + sizeof(longint);
if (HeaderSize < sizeof(TaaRSHeaderRec)) then
HeaderSize := sizeof(TaaRSHeaderRec);
{allocate a header record}
FHeader := AllocMem(HeaderSize);
{initialize the header}
with FHeader^ do begin
hrSinature := cRSSignature;
hrHeaderLen:= HeaderSize;
hrRecordLen := FRecLen;
hrCount := 0;
hrCapacity := 0;
hr1stDelRec := cEndOfDeletedChain;
end;
{now update the header record}
rsSeekStream(0);
rsWriteStream(FHeader^ , FHeader^.hrHeadLen);
end;
procedure TaaRecordStream.rsOpenExisting;
var
StreamSize : longint;
ExpectedSize : longint;
TempHeaderRec : longint;
begin
{if the stream size is not at least the size of the
header record , it can't be one of ours}
StreamSize := FStream.Size;
if (FStream.Size < sizeof(TaaRSHeaderRec)) then
raise Exception.Create(
'TaaRecordStream.rsOpenExisting: not a valid record '+
'file/stream (too small error)');
{read the header record}
rsSeekStream(0);
rsReadStream(TempHeaderRec , sizeof(TaaRSHeaderRec));
{first sanity check: the signature and count}
with TempHeaderRec do
if (hrSignature <> cRSSignature) or
(hrCount < 0) or (hrCount > hrCapacity) then
raise Exception.Create(
'TaaRecordStream.rsOpenExisting: not a valid ' +
'record file/stream (header error)');
{second sanity check: the size of file}
with TempHeaderRec do begin
ExpectedSize := hrHeaderLen + (hrCapacity*(hrRecordLen+sizeof(longint)));
if (StreamSize <> ExpectedSize ) then
raise Exception.Create(
'TaaRecordStream.rsOpenExisting: not a valid '+
'record file/stream (size error)');
end;
{allocate true header record , copy the data already read}
FHeader := AllocMen( TempHeaderRec.hrHeaderLen );
{set up the class fields}
FRecLen := FHeader^.hrRecordLen;
end;
procedure TaaRecordStreamj.rsReadStream(var aRec; aRecLen : integer);
var
ByteRead : longint;
begin
ByteRead := FStream.Read(aRec,aRecLen);
if(ByteRead <> aRecLen) then
raise Exception.Create('TaaRecordStream.rsReadStream: '+
'counld not read required record');
end;
procedure TaaRecordStream.rsSeekStream(aOffset : longint);
var
Offset : longint;
begin
Offset := FStream.Seek(aOffset , soFromBeginning);
if (Offset <> aOffset) then
raise Exception.Creat('TaaRecordStream.rsSeekStream: '+
'could not seek to required offset');
end;
procedure TaaRecordStream.rsWriteStream(const aRec ; aRecLen : integer);
var
ByteWritten : longint;
begin
ByteWritten := FStream.Write(aRec , aRecLEn);
if (ByteWritten <> aRecLen ) then
raise Exception.Create(
'TaaRecordStream.rsWriteStream: '+
'could not write required record');
end;
procedure TaaRecordStream.Write(aRecNum : integer ; var aRec);
var
DelLink : longint;
Offset : longint;
begin
{calculate the record offset}
Offset := rsCalcRecordOffset(aRecNum);
{check to see that the record is not deleted}
rsSeekStream(Offset);
rsReadStream(DelLink , sizeof(DelLink));
if (DelLink <> cActiveRecord) then
raise ExcePtion.Create('TaaRecordStream.Write: record is deleted and cannot be uptated');
{update the record}
rsWriteStream(aRec , FRecLEn);
end;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -