利用文件流存储自定义文件结构的方法

在程序中,我们需要用一个途径去把一些有规律的信息存储在磁盘上。当然方法有很多,如文本文件,CSVBDEADO、“File Of”类型文件等等。各有优缺点吧,这里我介绍自己使用的一种文件流的方法保存自定义的文件格式,速自定义加密、记录排序等算法。存取的速度也是比较快的。

首先

我们定义一下结构记录类型(呵呵,这个结构很熟悉,标准的树型结构):

 

PStructItem = ^TStructItem; TStructItem = record bid: string; pid: string; code: string; name: string; //……. end;   

 

然后我们在类中定义一下用于保存记录的Tlist对象以及一些操作记录的方法,如新增,删除、保存,加载等。

TNativeStructObj = class(TObject) Private FItems: TList; //… Public function Add(const Apid, Acode: string): PStructItem; procedure Delete(Index: Integer); procedure SaveToFile(const LogFileName: string); function LoadFromFile(const LogFileName: string): Boolean; //…… End;   

Add方法主要是新增记录,主要代码如下:

function TNativeStructObj.Add(const Apid, Acode: string): PStructItem; begin //…… New(p); p^.bid := vBID; p^.pid := Apid; p^.code := Acode; FItems.Add(p); Result := p; //…. End;   

Delete 方法主要是删除记录,主要代码如下:

procedure TNativeStructObj.Delete(Index: Integer); var p: PTreeStructItem; begin if (Index>= FItems.Count) or (Index<0) then raise Exception.Create('指定的索引超出了范围!'); p := FItems.Items[index]; Dispose(p); FItems.Delete(Index); //…… end;   

//返回单条记录的文本信息,用于保存到文件流中。

function TNativeStructObj.Item2Str(const Index: Integer): string; var s: string; p: PTreeStructItem; Size: Word; begin p := FTreeStructItems.Items[Index]; s := p^.bid + #9 + p^.pid + #9 + p^.code + #9 + p^.name; s := EncryptStr(s); // 加密要保存的内容 Size := Length(s); Result := WordStr(Size) + s; end;

//文章的重点,保存记录到文件

procedure TNativeStructObj.SaveToFile(const LogFileName: string); var fs: TFileStream; TmpStr: string; i: Integer; begin try fs := TFileStream.Create(LogFileName, fmCreate or fmShareExclusive); except raise Exception.Create('无法创建文件!'); end; try Sort; // 保存前先排序 // 保存头信息 FLastSaveTime := Now; TmpStr := HeadStr; //这个是返回文件头信息的函数。 fs.WriteBuffer(TmpStr[1], Length(TmpStr)); // 保存各记录 for i:=0 to FItems.Count-1 do begin TmpStr := Item2Str(i); //返回单条记录的信息 fs.WriteBuffer(TmpStr[1], Length(TmpStr)); end; finally fs.Free; end; end;   

//文章的重点,从文件中加载数据到列表

function TNativeStructObj.LoadFromFile(const LogFileName: string): Boolean; var fs: TFileStream; WordSize: Word; TmpStr, s: string; i, j, UserCount: Integer; p: PTreeStructItem; begin Result := False; try fs := TFileStream.Create(LogFileName, fmOpenRead or fmShareDenyWrite); except raise Exception.Create('无法打开文件!'); end; for i:=0 to FTreeStructItems.Count-1 do Dispose(PTreeStructItem(FTreeStructItems.Items[i])); FTreeStructItems.Clear; try // 读取文件头 fs.ReadBuffer(WordSize, 2); SetLength(TmpStr, WordSize); fs.ReadBuffer(TmpStr[1], WordSize); // 分析文件头 TmpStr := DecryptStr(TmpStr); // 先解密 s := Copy(TmpStr, 1, 4); iCount := PInteger(@s[1])^; // 获取记录数 s := Copy(TmpStr, 5, 19); FLastSaveTime := StrToDateTime(s, FmtSettings); // 最后保存时间 // 逐项读取解析各记录 i := 0; while i< iCount do begin fs.ReadBuffer(WordSize, 2); SetLength(TmpStr, WordSize); fs.ReadBuffer(TmpStr[1], WordSize); TmpStr := DecryptStr(TmpStr); // 先解密 New(p); j := 1; s := ''; while TmpStr[j]<>#9 do begin s:= s + TmpStr[j]; Inc(j); end; p^.bid := s; s := ''; Inc(j); while TmpStr[j]<>#9 do begin s:= s + TmpStr[j]; Inc(j); end; p^.pid := s; s := ''; Inc(j); while TmpStr[j]<>#9 do begin s:= s + TmpStr[j]; Inc(j); end; p^.code := s; s := ''; Inc(j); while TmpStr[j]<>#9 do begin s:= s + TmpStr[j]; Inc(j); end; p^.name := s; FItems.Add(p); Inc(i); end; finally fs.Free; end; end;   

 

结束语

至此,我们已经知道如何写记录到磁盘文件,如何读取,如何仅仅改变文件中间某条记录的一部分数据。

 

你可能感兴趣的:(Delphi专栏)