记录文件中如何正确保存string类型的"大"数据(超过256个字符)?(50分)

  • 主题发起人 主题发起人 wind98
  • 开始时间 开始时间
W

wind98

Unregistered / Unconfirmed
GUEST, unregistred user!
记录文件中如何正确保存string类型的"大"数据(超过256个字符)?
type
TMyRec = Record
a:string[10];
b:string;//要保存的数据比较大,所以这里用string而不用string[255];
end;

//保存成文件:
procedure SaveRec(sFN, sStr1, sStr2: string);
var
aRec : array of TMyRec;
var
FStr : TMemoryStream;
i : longint;
begin
{获得文件中的记录,如果文件不存在则为空}
GetAllRec(sFN);
{获得得文件中的记录数,如果文件不存在则为0}
i := GetRecNums(sFN);
SetLength(aRec, i + 1);
with aRec do
begin
a := sStr1;
b := sStr2;
end;
FStr := TMemoryStream.Create;
{记录数}
i := length(aRec);
{保存记录数}
FStr.Write(i, sizeof(i));
{保存数据}
for i := 0 to high(aRec) do
FStr.Write(aRec, sizeof(aRec)); //这一句有问题,无法正确保存数据,我想应该是无法确定其大小的原因
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//因为如果将b:string;改为b:string[255];则可以正确保存
FStr.SaveToFile(sFN);
FStr.Free;
end;
end;

 
用AnsiString吧
 
这个问题可不可以这么解
var
filecontent : Tstrings;
procedure SaveRec(sFN,sStr1, sStr2: string);
begin
if filecontent= nil then
filecontent := Tstringlist.create;
//添加对stringlist的操作
 filecontent.savetofile(sfn);
一切ok!
end;
 
to commons_sheng:
没用的,这个不是string或ansistring的原因,记录中的string类型可以保存很多的字符(超过256),
我们可以通过单步运行或用ShowMessage();来查看,就是保存的时候会出错,总是把不定长度的字段
(如b:string)给保存错误了,而对于定长的(如:a:string[10])就可以很好地保存。
to eric.youbin:
我不想用TStrings来处理,因为我上所举的只有两个"字段"而已,而实际上有很多个,
而且保存后还要读出来,一个"字段"一个"字段"地读,用TStrings有很多方面不好处理,
我也不想用数据库,所以只好用record来处理了。
大家继续...
 
to eric.youbin:你这种方法好象没有办法处理结构文件,只能处理纯文本文件。
这段时间我一直都在处理这种结构文件,我觉得象这种变长的字符串(String)不应该放
在记录中,我就是把他们分开处理的,也就是说有两个文件,一个是索引,一个存放内容。
 
to 教父:
能具体说说吗?最好能举例说明![8D]
 
比如你的记录可以这样定义:
MyRec=record
a:String[10];
StartPos,
Size:longint;
end;
然后再同时打开两个文件,记下内容文件的位置,写入StartPos,将内容的长度写入
Size,将内容写入内容文件,将结构写入索引文件。
 
to 教父:
你的方法也是可行的,不过,你要分两个文件来操作,无形中也给操作带来了不便。
昨天请教了一位同事,他提供了一种想法,就是用TStringStream来保存数据,然后
把TStringStream数据流倒入TMemoStream中,然后用TMemoStream保存成文件:)
我试了,可以!呵呵...代码如下:
const
sJG = '##';
procedure TForm1.SaveRec(sFN: string);
{保存记录}
var
FStr : Tstringstream;
FMemo : TMemoryStream;
i : longint;
ph : string;
begin
FStr := TstringStream.Create(ph);
for i := 0 to high(aRec) do
begin
FStr.WriteString(a+sJG); //每个"字段"之间用##隔开,具体用什么隔开可以自已定义
FStr.WriteString(b+sJG);
end;
FStr.Position := 0;
FMemo := TMemoryStream.Create;
FMemo.CopyFrom(FStr, FStr.Size); //倒入数据流到FMemo
FMemo.SaveToFile(sFN); //保存文件
FStr.Free;
end;

procedure TForm1.GetAllRec(sFN: string);
{读:获得记录内容}
var
slTmp1, slTmp2 : TStrings;
i, j, k : longint;
begin
slTmp1 := TStringList.Create;
slTmp2 := TStringList.Create;
if not FileExists(sFN) then Exit; //文件不存在退出
slTmp1.LoadFromFile(sFN);
CheckSite(slTmp1.Text, sJG, slTmp2); //把字符串以sJG为分隔符分开,保存在slTmp2中
SetLength(aRec, 1);
j := 0; //字段数记数器
k := 0; //记录数记数器
for i := 0 to slTmp2.Count - 1 do
begin
case j of
0: aRec[k].a := slTmp2;
1: aRec[k].b := slTmp2;
end;
if j >= high(aRec) then //到最后一个字段
begin
inc(k); //记录数加1
j := 0; //字段数清0,从第一个字段再开始
if i < slTmp2.Count - 1 then //slTmp2中还有数据
SetLength(aRec, high(aRec) + 2); //aRec添加一条记录
end
else inc(j); //下一个字段
end;
slTmp1.Free;
slTmp2.Free;
end;

function TForm1.CheckSite(const Str, Ch: string; var Mystring: TStrings)
: boolean;
{字符串Str以Ch分隔成几段小字符串,该函数是将这些小字符串提取出来并保存在MyString中}
var
sit, n : integer;
S : string;
begin
Result := True;
MyString.Clear;
S := Str;
n := Length(Ch);
while True do
begin
if Pos(Ch, S) = 0 then
begin
MyString.Add(S);
Break;
end;
sit := Pos(Ch, S);
MyString.Add(Copy(S, 1, sit - 1));
S := Trim(Copy(S, sit + n, Length(S)));
end;
if MyString.Count < 2 then Result := False;
end;

以上代码在Delphi5+Wind2000下调试运行通过。
 
多人接受答案了。
 
这样做是可以实现,可是这样写到一个文件中,好象不太容易实现如:检索、修改、删除
等操作。其实你看看DBF的结构,它也是把Memo部分单独分出来的。
 
to 教父:
我在GetAllRec(sFN: string);函数中其实已经把数据读到aRec中去了,检索、修改、删除
等操作直接对aRec操作就行了。
 
后退
顶部