Чтение онлайн

на главную - закладки

Жанры

О чём не пишут в книгах по Delphi

Григорьев Антон Борисович

Шрифт:

В проекте RecordWrite имеем следующий код (листинг 3.35).

Листинг 3.35. Неправильный метод записи структуры со строкой в файл 

type

 TMethod1Record = packed record

Hour: Word;

Minute: Word;

Second: Word;

MSec: Word;

Msg: string;

 end;

procedure TForm1.Button1Click(Sender: TObject);

var

 Rec: TMethod1Record;

 Stream: TFileStream;

begin

 DecodeTime(Now, Rec.Hour, Rec.Minute, Rec.Second, Rec.MSec);

 Rec.Msg := Edit1.Text;

 Stream := TFileStream.Create('Method1.stm', fmCreate);

 Stream.WriteBuffer(Rec, SizeOf(Rec));

 Stream.Free;

end;

В

проекте RecordRead соответствующий код (листинг 3.36).

Листинг 3.36. Неправильный метод чтения структуры со строкой из файла

procedure TForm1.Button1Click(Sender: TObject);

var

 Rec: TMethod1Record;

 Stream: TFileStream;

begin

 Stream := TFileStream.Create('Method1.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;

Примечание

В проекте RecordRead объявлена такая же запись

TMethod1Record
, описание которой во втором случае для краткости опущено.

Запись в файл происходит нормально, но при чтении в строке, отмеченной звездочкой, скорее всего, возникает исключение Access violation (в некоторых случаях исключения может не быть, но вместо сообщения будет выведен мусор). Причину этого мы уже обсудили ранее — указатель

Msg
, действительный в контексте процесса RecordWrite, не имеет смысла в процессе RecordRead, а сама строка передана не была. Без ошибок этим методом можно передать только пустую строку, потому что ей соответствует указатель
nil
, имеющий одинаковый смысл во всех процессах. Однако метод передачи строк, умеющий передавать только пустые строки, имеет весьма сомнительную ценность с практической точки зрения.

Самый простой способ исправить ситуацию— изменить тип поля

Msg
на
ShortString
. Больше ничего в приведенном коде менять не придется. Однако использование
ShortString
имеет два недостатка. Во-первых, длина строки в этом случае ограничена 255 символами. Во-вторых, если длина строки меньше максимально возможной, часть памяти, выделенной для структуры, останется незаполненной. Если средняя длина строки существенно меньше максимальной, то таких неиспользуемых кусков в потоке будет много, т.е. файл окажется неоправданно раздутым. Это всегда плохо, а в некоторых случаях — вообще недопустимо, поэтому
ShortString
можно посоветовать только в тех случаях, когда строки имеют примерно одинаковую длину (напомним, что
ShortString
позволяет ограничить длину строки меньшим, чем 255, числом символов — в этом случае поле будет занимать меньше места).

С одним из этих недостатков можно бороться: если заменить в записи

ShortString
статическим массивом типа
Char
, то можно передавать
строки большей, чем 255 символов, длины. Второй метод демонстрирует этот способ.

В проекте RecordWrite этому соответствует код (листинг 3.37).

Листинг 3.37. Запись в файл структуры с массивом символов

const

 MsgLen = 15;

type

 TMethod2Record = packed record

Hour: Word;

Minute: Word;

Second: Word;

MSec: Word;

Msg: array[0..MsgLen - 1] of Char;

 end;

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. Гибрид
Фантастика:
фэнтези
попаданцы
технофэнтези
аниме
5.00
рейтинг книги
Белые погоны

Черный дембель. Часть 1

Федин Андрей Анатольевич
1. Черный дембель
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Черный дембель. Часть 1

Лишняя дочь

Nata Zzika
Любовные романы:
любовно-фантастические романы
8.22
рейтинг книги
Лишняя дочь

Темный Лекарь 5

Токсик Саша
5. Темный Лекарь
Фантастика:
фэнтези
аниме
5.00
рейтинг книги
Темный Лекарь 5

Последний из рода Демидовых

Ветров Борис
Фантастика:
детективная фантастика
попаданцы
аниме
5.00
рейтинг книги
Последний из рода Демидовых

Чиновникъ Особых поручений

Кулаков Алексей Иванович
6. Александр Агренев
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Чиновникъ Особых поручений

Попаданка в академии драконов 4

Свадьбина Любовь
4. Попаданка в академии драконов
Любовные романы:
любовно-фантастические романы
7.47
рейтинг книги
Попаданка в академии драконов 4

Боги, пиво и дурак. Том 6

Горина Юлия Николаевна
6. Боги, пиво и дурак
Фантастика:
фэнтези
попаданцы
5.00
рейтинг книги
Боги, пиво и дурак. Том 6

Курсант: Назад в СССР 10

Дамиров Рафаэль
10. Курсант
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Курсант: Назад в СССР 10

Сделай это со мной снова

Рам Янка
Любовные романы:
современные любовные романы
5.00
рейтинг книги
Сделай это со мной снова

Болотник 2

Панченко Андрей Алексеевич
2. Болотник
Фантастика:
попаданцы
альтернативная история
6.25
рейтинг книги
Болотник 2

Камень Книга двенадцатая

Минин Станислав
12. Камень
Фантастика:
боевая фантастика
городское фэнтези
аниме
фэнтези
5.00
рейтинг книги
Камень Книга двенадцатая

Небо для Беса

Рам Янка
3. Самбисты
Любовные романы:
современные любовные романы
5.25
рейтинг книги
Небо для Беса

Надуй щеки! Том 4

Вишневский Сергей Викторович
4. Чеболь за партой
Фантастика:
попаданцы
уся
дорама
5.00
рейтинг книги
Надуй щеки! Том 4