record类型的动态数组如何快速保存到文件,如何从文件加载。(100分)

  • 主题发起人 主题发起人 qqjm
  • 开始时间 开始时间
Q

qqjm

Unregistered / Unconfirmed
GUEST, unregistred user!
定义如下:
PTMyRecord=^TMyRecord;
TMyRecord= Record
id:integer;
Msg:string[255]
Time:TDatetime;
Next:PTMyRecord;
end;
........
........
MyRecord:=array of TMyRecord;
..........

假设Length(MyRecord)=10;

如何可以快速把它保存到文件,并且可以正确从文件中加载。

请各位提供点资料。

(11月24日下午结帖)
 
如下:
var
tmpStream: TStream;
MyRecord: array of TMyRecord;
tmpCount, i: Integer;
begin
tmpStream := TFileStream.Create('c:/123.dat', fmCreate or fmOpenReadWrite);
try
{----读文件----}
tmpStream.Position := 0;
tmpStream.read(tmpCount, SizeOf(Integer));
SetLength(MyRecord, tmpCount);
for i := 0 to tmpCount - 1 do
tmpStream.read(MyRecord, SizeOf(TMyRecord));
{----写文件----}
tmpStream.Position := 0;
tmpStream.Write(High(MyRecord) + 1, SizeOf(Integer));
for i := Low(MyRecord) to High(MyRecord) do
tmpStream.Write(MyRecord, SizeOf(TMyRecord));
finally
tmpStream.Free;
end;
end;
 
我的控件中的一段代码, 存入流后,想存取文件就存取文件(TmemoryStream.savetofile loadfromfile), 想存取到数据库也是一样,动态记录。string类型等所有指针类数据结构都可以用我这个方法
type
TDataBaseType=(DT_standard,DT_Oracle,DT_DB2,DT_SQLSever,DT_Access,
DT_Sybase,DT_MySQL,DT_InterBase,DT_Informix,DT_Other,
DT_none);

byte256s= array of byte256;
R_BeskyDBLink=record
name:shortString;
DBType:TDataBaseType;
Linkstr:byte256s;
end;
const
MS_R_BeskyDBLink:integer=501;
Ms_Byte256s:integer=52;
function intSaveToStream(I:integer;ms:TMemoryStream):boolean;
function intLoadFromStream(var I:integer;ms:TMemoryStream):boolean;

function dataSaveToStream(bts:byte256s;ms:TMemoryStream):boolean;overload;
function dataLoadFromStream(var bts:byte256s;ms:TMemoryStream):boolean;overload;

function CopyRecord(Rs:R_BeskyDBLink;var RD:R_BeskyDBLink):boolean;overload;
function DisposeRecord(Var R:R_BeskyDBLink):boolean;overload;
function dataSaveToStream(R:R_BeskyDBLink;ms:TMemoryStream):boolean;overload;
function dataLoadFromStream(var R:R_BeskyDBLink;ms:TMemoryStream):boolean;overload;
//............
function intSaveToStream(I:integer;ms:TMemoryStream):boolean;
begin
result:=false;
if not assigned(ms) then exit;
try
ms.Write(i,sizeof(i));
result:=true;
except
on E : Exception do
Application.MessageBox(PansiChar(E.Message+'错误号:'+inttostr(E.HelpContext)),'错误!',MB_OK+MB_ICONERROR+MB_TOPMOST);
end;
end; //integer
function intLoadFromStream(var I:integer;ms:TMemoryStream):boolean;
begin
result:=false;
if not assigned(ms) then exit;
try
ms.Read(i,sizeof(i));
result:=true;
except
on E : Exception do Application.MessageBox(PansiChar(E.Message+'错误号:'+inttostr(E.HelpContext)),'错误!',MB_OK+MB_ICONERROR+MB_TOPMOST);
end;
end; //integer

function dataLoadFromStream(var bts:byte256s;ms:TMemoryStream):boolean;overload;
var
datatype:integer;
count,i:integer;
// sss:shortstrings;
begin
result:=false;
if not assigned(ms) then exit;
if not intloadfromStream(datatype,ms) then exit;
if datatype<>Ms_byte256s then exit;
if not intloadfromStream(count,ms) then exit;
if count=0 then exit;
setlength(bts,count);
try
for i:=0 to count-1 do ms.Read(bts,256);
result:=true;
except
on E : Exception do
Application.MessageBox(PansiChar(E.Message+'错误号:'+inttostr(E.HelpContext)),'错误!',MB_OK+MB_ICONERROR+MB_TOPMOST);
end;

end;
function dataSaveToStream(bts:byte256s;ms:TMemoryStream):boolean;overload;
var
i,count:integer;
begin
result:=false;
if not assigned(ms) then exit;
try
count:=high(bts)+1;
if not intSaveToStream(Ms_byte256s,ms) then exit;
if not intSaveToStream(count,ms) then exit;
if count=0 then exit;
for i:=0 to count-1 do
ms.Write(bts,256);
result:=true;
except
on E : Exception do
Application.MessageBox(PansiChar(E.Message+'错误号:'+inttostr(E.HelpContext)),
'错误!',MB_OK+MB_ICONERROR+MB_TOPMOST);
// messagedlg(E.Message,mtError ,[mbOK], E.HelpContext);
end;

end;

function CopyRecord(Rs:R_BeskyDBLink;var RD:R_BeskyDBLink):boolean;
begin
result:=false;
try
DisposeRecord(rd);
RD:=RS;
RD.Linkstr:=copy(RS.Linkstr);
result:=true;
except
on E: Exception do
Application.MessageBox(PansiChar(E.Message+'错误号:'+inttostr(E.HelpContext)),
'错误!',MB_OK+MB_ICONERROR+MB_TOPMOST);
end;
end;
function DisposeRecord(Var R:R_BeskyDBLink):boolean;
begin
result:=false;
try
setlength(r.Linkstr,0);
result:=true;
except
on E: Exception do
Application.MessageBox(PansiChar(E.Message+'错误号:'+inttostr(E.HelpContext)),
'错误!',MB_OK+MB_ICONERROR+MB_TOPMOST);
end;
end;
function dataSaveToStream(R:R_BeskyDBLink;ms:TMemoryStream):boolean;overload;
begin
result:=false;
if not assigned(ms) then exit;
try
if not intSaveToStream(Ms_R_BeskyDBLink,ms) then exit;
ms.Write(R.name,256);
ms.Write( R.DBType,sizeof( R.DBType));
dataSaveToStream(R.Linkstr,ms);
result:=true;
except
on E : Exception do
Application.MessageBox(PansiChar(E.Message+'错误号:'+inttostr(E.HelpContext)),
'错误!',MB_OK+MB_ICONERROR+MB_TOPMOST);
end;
end; // R_BeskyPanel
function dataLoadFromStream(var R:R_BeskyDBLink;ms:TMemoryStream):boolean;overload;
var
datatype:integer;
begin
result:=false;
if not assigned(ms) then exit;
try
if not intloadfromStream(datatype,ms) then exit;
if datatype<>Ms_R_BeskyDBLink then exit;
DisposeRecord(R);
ms.read(R.name,256);
ms.read( R.DBType,sizeof( R.DBType));
DataloadfromStream(R.Linkstr,ms);
result:=true;
except
on E : Exception do
Application.MessageBox(PansiChar(E.Message+'错误号:'+inttostr(E.HelpContext)),
'错误!',MB_OK+MB_ICONERROR+MB_TOPMOST);
end;

end;
 
还有问题,Next:PTMyRecord;是做什么用的?既然是链表,为什么还用数组呢?
{----读文件改如下----}
tmpStream.Position := 0;
tmpStream.read(tmpCount, SizeOf(Integer));
SetLength(MyRecord, tmpCount);
for i := 0 to tmpCount - 1 do
begin
tmpStream.read(MyRecord, SizeOf(TMyRecord));
if i > 0 then
MyRecord[i - 1].Next := @(MyRecord)
end;
 
不好意思!同类函数太多(我几乎定义了我所有用到),贴错了好几回。现在该正确了!
 
谢谢两位提供资料。
-----------------
回nicai_wgl
  因为这队列插入和删除比较频繁,Next是指向下一个“空”的项,这样我就不用再查那些已经删除的。
  其实我还有个指针数组指向些“非空”数据,这个指针数组是已经做了排序的,我用这个指针数据做快速查询用。
 
看了你们两个的方法,我觉得都可以用,但是nicai_wgl的方法是最适合我这里使用,因为我的记录是定长的。
而bmsr的方法可以用在不定长的记录里,这个我以后要用到,谢谢了。
 

Similar threads

S
回复
0
查看
3K
SUNSTONE的Delphi笔记
S
S
回复
0
查看
2K
SUNSTONE的Delphi笔记
S
S
回复
0
查看
928
SUNSTONE的Delphi笔记
S
后退
顶部