Читаем О чём не пишут в книгах по Delphi полностью

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).

Листинг 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)

Листинг 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).

Листинг 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;

Перейти на страницу:
Нет соединения с сервером, попробуйте зайти чуть позже