procedure TForm1.Button2Click(Sender: TObject);
var
Rес: TMethod2Record;
Stream: TFileStream;
begin
DecodeTime(Now, Rec.Hour, Rec.Minute, Rес. Second, Rec.MSec);
StrPLCopy(Rec.Msg, Edit1.Text, MsgLen — 1);
Stream:= TFileStream.Create('Method2.stm', fmCreate);
Stream.WriteBuffer(Rec, SizeOf(Rec));
Stream.Free;
end;
В проекте RecordRead это следующий код (листинг 3.38).
procedure TForm1.Button2Click(Sender: TObject);
var
Rес: TMethod2Record;
Stream: TFileStream;
begin
Stream:= TFileStream.Create('Method2.stm', fmOpenRead);
Stream.ReadBuffer(Rec, SizeOf(Rec));
Stream.Free;
Label1.Caption:=
TimeToStr(EncodeTime(Rec.Hour, Rec.Minute, Rec.Second, Rec.MSec));
Label2.Caption:= Rec.Msg;
end;
Константа MsgLen
задаёт максимальную (вместе с завершающим нулём) длину строки. В приведенном примере она взята достаточно маленькой, чтобы наглядно продемонстрировать, что данный метод имеет ограничения на длину строки. Переделки по сравнению с кодом предыдущего метода минимальны: при записи для копирования значения Edit1.Text
вместо присваивания нужно вызывать функцию StrPLCopy
. В коде RecordRead
изменений (за исключением описания самой структуры) вообще нет — это достигается за счёт того, что массив Char
считается компилятором совместимым с PChar
, а выражения типа PChar
могут быть присвоены переменным типа AnsiString
— конвертирование выполнится автоматически.
Однако проблему неэффективного использования файлового пространства мы таким образом не решили. Более того, мы до конца не решили и проблему максимальной длины: хотя ограничение на длину строки теперь может быть произвольным, всё равно оно должно быть известно на этапе компиляции. Чтобы полностью избавиться от этих проблем, необходимо вынести строку за пределы записи и сохранить её отдельно, вместе с длиной, чтобы при чтении сначала читалась длина строки, затем выделялась для неё память, и в эту память читалась строка. Именно так работает третий метод. В проекте Record Write это будет следующий код (листинг 3.39)
type
TMethod3Record = packed record
Hour: Word;
Minute: Word;
Second: Word;
MSec: Word;
end;
procedure TForm1.Butrton3Click(Sender: TObject);
var
Rec: TMethod3Record;
Stream: TFileStream;
Msg: string;
MsgLen: Integer;
begin
DecodeTime(Now, Rec.Hour, Rec.Minute, Rec.Second, Rec.MSec);
Msg:= Edit1.Text;
MsgLen:= Length(Msg);
Stream:= TFileStream.Create('Method3.stm', fmCreate);
Stream.WriteBuffer(Rec, SizeOf(Rec));
Stream.WriteBuffer(MsgLen, SizeOf(MsgLen);
if MsgLen > 0 then Stream.WriteBuffer(Pointer(Msg)^, MsgLen);
Stream.Free;
end;
В проекте RecordRead это следующий код (листинг 3.40).
procedure TForm1.Button3Click(Sender: TObject);
var
Rec: TMethod3Record;
Stream: TFileStream;
Msg: string; MsgLen:
Integer;
begin
Stream:= TFileStream.Create('Method3.stm', fmOpenRead);
Stream.ReadBuffer(Rec, SizeOf(Rec));
Stream.ReadBuffer(MsgLen, SizeOf(Integer));
SetLength(Msg, MsgLen);
if MsgLen > 0 then Stream.ReadBuffer(Pointer(Msg)^, MsgLen);
Stream.Free;
Label1.Caption:=
TimeToStr(EncodeTime(Rec.Hour, Rec.Minute, Rec.Second, Rec.MSec));
Label2.Caption:= Msg;
end;