От Delphi 4 к Delphi 5 часть 34

От Delphi 4 к Delphi 5 Файлы
Файл представляет собой именованную область памяти персонального компьютера (винчестера, диска 3.5", диска CD).
Файл имеет имя, содержит компоненты одного типа. Длина создаваемого файла никак не оговаривается при его объявлении и ограничивается только емкостью устройств внешней памяти.
В программе файл представлен последовательностью элементов некоторого типа. Размер одного файла может превышать объем всей оперативной памяти компьютера, в этом случае доступ к его элементам выполняется последовательно с помощью процедур чтения и записи.
Для файла существует понятие текущей позиции. Она показывает номер элемента, который будет прочитан или записан при очередном обращении к файлу. Чтение-запись каждого элемента продвигает текущую позицию на единицу вперед. Для большинства файлов можно менять текущую позицию чтения-записи, выполняя прямой доступ к его элементам.
Файловый тип объявляется следующим образом:
<имя> = File of <тип> ; или
<имя> = TextFile; или
<имя> = File;
где <имя> — имя файлового типа File, of — зарезервированные слова. TextFile — имя стандартного типа текстовых файлов. <тип> любой тип Object Pascal.
В зависимости от типа элемента различают файлы трех видов: текстовые файлы, типизированные файлы и не типизированные файлы.
Текстовые файлы состоят из последовательностей символов, разбитых на строки. В Object Pascal предопределен тип TextFile, соответствующий текстовому файлу. Таким образом, объявление файловой переменной может иметь вид:
var <имя файловой переменной> : TextFile;
Например:
var
N: TextFile;
Работа с текстовыми файлами осуществляется процедурами и функциями файлового ввода/вывода. Основные процедуры чтения — Read, Readln, Write и Writeln.
Типизированные файлы являются двоичными файлами, содержащими последовательность однотипных данных. Файл состоит из элементов фиксированного размера, элементами которого чаще всего являются записи. Объявление файловых переменных имеет вид:
var <имя файловой переменной> : File of <тип данных> ;
Например:
var
F: File of real;
Процедуры чтения и записи Read и Write не отличаются от соответствующих процедур для текстовых файлов. Процедур, аналогичных Readln и Writeln, для типизированных файлов нет. Зато есть процедура Seek, позволяющая перемещаться по файлу не только последовательно, как в текстовых файлах, но сразу переходить к требуемому элементу. Имеется также функция FilePos, которая возвращает текущую позицию в файле.
Не типизированные файлы — это двоичные файлы, которые могут содержать самые различные данные в виде последовательности байтов. Файл состоит из элементов переменного размера. Программист при чтении этих данных сам должен разбираться, какие байты к чему относятся.
Тип файловой переменной не типизированного файла объявляется следующим образом:
var <имя файловой переменной> : File;
Например:
var
M: File;
Открытие не типизированных файлов осуществляется процедурами Reset и Rewrite, синтаксис которых несколько отличен от аналогичных процедур для других видов файлов тем, что в этих процедурах указывается размер одной записи в байтах. Вместо процедур записи и чтения Read и Write, в не типизированных файлах имеются процедуры BlockRead и BlockWrite, которые читают или записывают указанное в них число записей.
Рассмотрим пример определения файлов.
type
Data = record
Surname: String;
TheCod: Word;
Part: Comp;
Name: array [1..25] of Char;
end;
Text100 = File of String [100];
var
N1: File of Char;
N2: TextFile;
N3: File;
N4: Text100;
InFile: File of Word;
end.
Файлы становятся доступны программе только после выполнения особой процедуры открытия файла. Эта процедура заключается в связывании ранее объявленной файловой переменной с именем существующего или вновь создаваемого файла, а также в указании направления обмена информацией: чтение из файла или запись в него.
Файловая переменная связывается с именем файла в результате обращения к стандартной процедуре AssignFile.
AssignFile (<файловая переменная>, <имя файла> );
где (<файловая переменная> — правильный идентификатор, объявленный в программе как переменная файлового типа;
<имя файла> — текстовое выражение, содержащее имя файла и, если это необходимо, маршрут доступа к нему.
Инициировать файл означает указать для этого файла направление передачи данных.
В Object Pascal можно открыть файл для чтения, для записи информации, а также для чтения и записи одновременно.
Инициирование файла для чтения производится с помощью стандартной процедуры Reset:
Reset (<файловая переменная> );
Здесь файловая переменная, связанная ранее процедурой AssignFile с уже существующим файлом.
При выполнении этой процедуры дисковый файл подготавливается к чтению информации. В результате специальная переменная-указатель, связанная с этим файлом, будет указывать на начало файла, т.е. на компонент с порядковым номером 0.
procedure AssignFile(var F; FileName: string);
Рассмотрим пример использования этой процедуры.
Для этого поместите на форму компонент Edit1, OpenDialog1, Button1.
Программный код представлен ниже.
procedure TForm1.Button1 Click(Sender: TObject);
var
F: TextFile;
S: string;
begin
if OpenDialog1.Execute then {Активизация диалогового окна}
begin
AssignFile(F, OpenDialog1. FileName); {Поиск нужного файла}
Reset(F);
Readln(F, S); {Чтение первой строки из файла}
Edit1.Text:= S; {Помещение строки в компонент Edit1}
CloseFile(F);
end;
end;
end.
Щелчок по кнопке открывает диалоговое окно поиска необходимого файла. После выбора файла и щелчка по кнопке "Открыть" в текстовый редактор записывается строка файла.
Для текстовых файлов, открытых процедурой Reset, нельзя использовать процедуру Write или Writeln.
Стандартная процедура Rewrite инициирует запись информации в файл, связанный с файловой переменной.
procedure Rewrite(var F: File [; Recsize: Word ]);
процедура перезаписи создает новый внешний файл с именем F.
RecSize — необязательное выражение, которое может быть определено, только если F — файл неопределенного типа. В этом случае RecSize определяет размер записи, который нужно использовать при передаче данных. Если RecSize опущен, задается по умолчанию размер записи в 128 байт.
Если внешний файл с тем же самым именем уже существует, то он удаляется и новый пустой файл создается на его месте.
Если F уже открыт, то сначала он закрывается и затем обновляется. Текущая позиция файла установлена в начало пустого файла.
var F: TextFile;
begin
AssignFile(F, 'NEWFILE.$$$');
Rewrite(F);
Writeln(F, 'Только созданный файл с этим текстом в этом...');
CloseFile(F);
end;

Стандартна процедура Append
procedure Append(var F: Text);
инициирует запись в ранее существовавший текстовый файл для его расширения, при этом указатель файла устанавливается в его конец. Эта процедура применима только к текстовым файлам, т.е. их файловая переменная должна иметь тип TextFile.
С ее помощью нельзя инициировать запись в типизированный или не типизированный файл. Если текстовый файл уже открыт с помощью Reset или Rewrite, использование процедуры Append приведет к закрытию этого файла и открытию его вновь, но уже для добавления записей.
var
F: TextFile;
begin
if OpenDialog1.Execute then
begin
AssignFile(f, OpenDialog1. FileName);
Append(f);
Writeln(f, 'Я добавляю некоторый материал к концу файла.');
{Вставьте код, который обеспечивает сброс перед закрытием файла}
Flush(f);
CloseFile(f);
end;
end;
Процедуры и функции файлового ввода/вывода
Append — открывает существующий текстовый файл, связанный с файловой переменной F, для добавления в конец файла.
AssignFile — связывает имя внешнего файла FileName с файловой переменной F.
BlockRead читает Count записей из не типизированного файла, связанного с файловой переменной F, в буфер Buf. Если задан параметр Result, то в него возвращается число действительно прочитанных записей.
BlockWrite — записывает Count записей из буфера Buf в не типизированный файл, связанный с файловой переменной F. Если задан параметр Result, то в него возвращается число действительно произведенных записей.
ChDir(S: string) — изменяет текущий каталог на каталог заданный параметром S.
CloseFile(Var F) — закрывает открытый файл, связанный с файловой переменной F.
Eof(var F):Boolean — возвращает True при достижении конца файла, связанного с файловой переменной F.
Eoln(var F: Text): Boolean — возвращает признак конца строки (True) в текстовом файле, связанном с файловой переменной F.
Erase(var F) — удаляет внешний файл, связанный с файловой переменной F.
FilePos(var F): Longint — возвращает текущую позицию типизированного или не типизированного файла, связанного с файловой переменной F. Позиция, соответствующая началу файла — 0.
FileSize(var F):Integer — возвращает текущий размер файла, связанного с файловой переменной F. Не используется для текстовых файлов.
Flush(var F: Text) — очищает буфер выходного текстового файла, связанного с файловой переменной F.
GetDir — возвращает S — текущий каталог диска, указанного параметром D, который может равняться: 0 — текущий диск, 1 — диск A, 2 — диск B, 3 — диск C и т.д. Каталог заносится в S без заключительного символа слэш, например, "c:\mydir".
IOResult: Integer — возвращает целое значение, которое характеризует код ошибки выполнения, последней операции ввода/вывода.
MkDir(S: String) — создает подкаталог, заданный с полным путем параметром S.
Read(F, <список переменных> ) — читает из файла, связанного с файловой переменной F, одно или более значений в одну или более переменных.
Readln(var F: Text; <список Переменных> ) — читает одно или более значений в одну или более переменных и переходит на начало следующей строки текстового файла, связанного с файловой переменной F.
Rename(var F; Newname) — переименовывает внешний файл, связанный с файловой переменной F, давая ему имя Newname. Переименование может сочетаться с переносом в другой каталог и на другой диск, если в Newname указан полный путь к переименованному файлу.
Reset(var F [: File;RecSize: Word]) — открывает существующий файл, связанный с файловой переменной F. Параметр RecSize задается для не типизированных файлов и устанавливает длину записи в байтах (по умолчанию 128).
Rewrite(var F: File [; Recsize:Word]) — создает и открывает новый файл, связанный с файловой переменной F. Параметр RecSize задается для не типизированных файлов и устанавливает длину записи в байтах (по умолчанию 128).
RmDir(S: String) — удаляет пустой подкаталог, заданный параметром S.
Seek(var F; N: Longint) — перемещает текущую позицию в типизированном или не типизированном файле, связанном с файловой переменной F, в позицию N. Для текстовых файлов не используется.
SeekEof (Var F: Text): Boolean — возвращает True при достижении конца текстового файла, связанного с файловой переменной F.
SeekEoln (Var F: Text): Boolean возвращает True при достижении конца строки текстового файла, связанного с файловой переменной F.
SetTextBuf(Var F: Text; Var Buf [; Size: Integer]) — cвязывает буфер ввода-вывода Buf размера Size (задавать не обязательно) с текстовым файлом, связанным с файловой переменной F.
Truncate(var F) — усекает типизированный или не типизированный файл, связанный с файловой переменной F, на текущей позиции.
Write(var F; <список выражений> ) — записывает одно или более значений в файл, связанный с файловой переменной F.
Writeln(var F: Text;<список выражений > ) — записывает одно или более значений в файл и затем заносит маркер конца строки в текстовый файл, связанный с файловой переменной F.

Компонент ActionList
Начиная с Delphi 4, появилась возможность систематизирования и упорядочивания разработки объектно-ориентированных приложений, что позволяет сэкономить немало времени при проектировании. Этот компонент позволяет производить диспетчеризацию событий.
Имеется такое понятие, как действие (action), т.е. некоторое поведение, проявляющееся в реакции на действия пользователя, например, щелчок по кнопке. В Delphi разработан класс Action, который вместе с его наследниками реализует многие стандартные действия, характерные для приложений Windows.
Компонент ActionList (список действий) содержит предусмотренные в приложении действия.
Объект ActionLink — редактор связей, поддерживает связь между действиями и инициаторами действий, он определяет, какое действие должно выполняться для данного инициатора. Главная цель действия — это объект, в котором отображается результат действия.
Перед началом проектирования приложения вы должны представить себе список действий, которые будете производить, может быть не окончательный, но хотя бы первый вариант. Его практическая реализация начинается с переноса на проектируемую форму не визуального компонента ActionList.
Одним из преимуществ использования списка действий является то, что заголовки обработчиков приобретают осмысленной характер и код становится более прозрачным. В результате вы избавляетесь от необходимости давать осмысленные имена кнопкам и разделам меню, т.е. облегчаете свою работу с компонентами. Как это происходит и насколько это удобно, можете определить, проделав действия, описанные ниже.
Рассмотрим пример использования компонента ActionList.
В нем проведем перевод градусной меры в радианную и обратно. Основный смысл использования компонента ActionList заключается в том, что вы сначала определяете необходимые действия в приложении. Например, первое действие производит перевод градусной меры в радианную. Второе действие производит перевод значения радиана в градусную меру. Затем вы производите связь выбранных компонентов, например кнопок или элементов меню, через их свойство Action с заданными вами действиями.
Вспомним теорию. Наряду с градусной мерой углов в тригонометрии употребляется и другая мера, называемая радианной мерой. В ней за единицу измерения принимается острый угол, под которым видна из центра окружности ее дуга MN, равная радиусу (дуга MN = OM). Такой угол называется радианом. На рисунке 3 вместе с размещением компонентов показан угол MON и дуга MN равная радиусу. Величина этого угла не зависит от радиуса окружности и от положения дуги MN на окружности. Так как полуокружность видна из центра под углом 180°, а длина ее равна p радиусам, то радиан в p раз меньше, чем угол в 180°, т.е. один радиан равен 180/p градусов. Обратно один градус равен p/180.
Чтобы найти радианную меру какого-нибудь угла по данной градусной его мере, необходимо умножить число градусов на p/180, число минут на p/180/60, а число секунд на p/180/60/60 и найденные произведения сложить.
Чтобы найти градусную меру угла по данной его радианной мере, необходимо умножить число радианов на 180/p.
1. Запустите Delphi.
2. Сохраните файл модуля под именем TheListOfOper_.pas, а файл проекта под именем TheListOfOper.dpr.
3. Поместите на форму компонент ActionList со страницы Standard. Произведите двойной щелчок по компоненту — откроется редактор действий, который позволит вводить и упорядочивать действия.
4. Щелкните мышью по кнопке со стрелкой, расположенной в левом верхнем углу редактора действий. В раскрывшемся меню можете выбрать одну из двух команд New Action (новое действие) или New Standard Action... (новое стандартное действие). По умолчанию действиям будут присваиваться имена Action1, Action2 и т.д. New Action позволяет вводить новое действие любого типа. New Standard Action... открывает окно, в котором вы можете выбрать стандартное действие или несколько действий. После выбора в правой части окна редактора какого-либо действия в левой части окна появится имя выбранного действия. Каждое внесенное в список действие является объектом типа Action для нестандартных действий или других производных типов для стандартных действий. После того, как вы выберите какую-либо категорию в правом окне редактора действий, в инспекторе объекта появляются его свойства и события.
5. Выберите действие, например, TEditCopy. В правой части окна редактора действий оно появляется с именем Edit1Copy. Активизируйте его, и в инспекторе объекта вы можете изменить имя в свойстве Name, которое будет у вас фигурировать в заголовках обработчиков событий.
6. Произведите изменение заголовка для данного действия, используя свойство Caption инспектора объекта, введите слово "Копировать" взамен принятого по умолчанию &Copy.
7. Вы можете назначить быстрые клавиши (ShortCut), например Ctrl+Alt+B, для этого раскройте список справа от свойства ShortCut и произведите выбор.
8. Если этот механизм вам стал понятен, то перейдем к нашему примеру. Удалите введенные действия, используя щелчок правой кнопкой мыши над ними. Появится всплывающее меню, из которого выберите команду Delete. Откройте редактор связей. Произведите щелчок по кнопке со стрелкой New Action (Ins). В раскрывшемся списке выберите команду New Action Ins. В правой части редактора связей появится первое действие Action1. Найдите на странице Properties свойство Category, которое в данный момент имеет значение (None). Измените его, например, на "Перевод". В левом окне редактора свойств появится категория "Перевод". После выделения этой категории появляется введенное действие Action1. Для нашего примера введите еще одно действие Action2. Для ввода нового действия есть два пути. Щелчок правой кнопкой мыши открывает всплывающее меню, содержащее команду New Action. Или можете вновь выбрать New Action (Ins) в верней части редактора связей.
9. Используя свойство Name, введите для действия Action1 новое имя Radian, для действия Action2 — имя Degree.
10. Используя свойство Caption, введите заголовки "Радиан" и "Градус" соответственно.
11. Поместите два компонента GroupBox для группирования элементов по функциональному назначению.
12. Поместите четыре компонента Label и, используя свойства Caption, введите соответствующие заголовки: "Градусы", "Минуты", Секунды", "Радианы".
13. Поместите компоненты: Edit1 для ввода значений градусов; Edit2 для ввода значений минут; Edit3 для ввода значений секунд; Edit4 для ввода значений радиан.
14. Активизируйте действие с именем Radian, в инспекторе объекта перейдите на страницу Events, выберите событие OnExecute. Произведите по нему двойной щелчок и напишите для него программный код, который показан ниже. Так же произведите выбор действия с именем Degree. Выберите событие OnExecute, произведите по нему двойной щелчок и напишите для него программный код, который показан ниже.
15. Поместите на форму две кнопки Button1, Button2. Теперь мы дошли до последнего завершающего момента, в котором определим для кнопок сформированные действия. Произведите активизацию кнопки Button1, перейдите к инспектору объекта на страницу Properties. Найдите свойство Action (действия). Щелкните справа от свойства, раскроется окно с именами двух действий, сформированных вами (рисунок 4). Произведите выбор имени Radian.
В такой же последовательности проведите выбор имени Degree для кнопки Button2. Сразу же после выбора вы можете видеть, как, например, копка Button1 приобретает заголовок "Радиан". Если вы теперь произведете двойной щелчок по кнопке, то раскроется окно редактора кода в том месте кода, которое связано с действием, имеющим имя Radian. Вы можете поместить на форму компонент MainMenu и аналогичным образом можете осуществить связь с элементами меню.
Программный код имеет следующий вид:
procedure TForm1.RadianExecute(Sender: TObject);
var
Grad,Min,Sec,Res:Real;
begin
Grad:=StrToFloat(Edit1.Text);
Min:=StrToFloat(Edit2.Text);
Sec:=StrToFloat(Edit3.Text);
Res:=Grad*pi/180 + Min*pi/ 180/60 + Sec*Pi/180/60/60;
Edit4.Text:=FloatToStr(Res);
end;
procedure TForm1.DegreeExecute(Sender: TObject);
var
Rad,Res:Real;
begin
Rad:=StrToFloat(Edit5.Text);
Res:=Rad*180/pi;
Edit6.Text:=FloatToStr(Res);
end;
end.
Но вы можете доработать созданное приложение. Для этого поместите на форму компонент ImageList со страницы Win32. Добавьте изображения в компонент, которые соответствуют, по вашему мнению, выбранным действиям. Можете использовать следующий путь для поиска изображений: Program Files\Common Files\Borland Shared\Images\Buttons. Введите для выбранных действий индекс изображения, которое соответствует данному действию в отдельном компоненте списка изображений ImageList1. Значение индекса начинается с нуля, этот индекс в дальнейшем передается компонентам, связанным с данным событием, например разделам меню, кнопкам и т.д. В нашем случае для кнопок. Определите для действия Radian в инспекторе объекта в свойстве ImageIndex значение 0, для действия Degree определите значение 1. Эти значения будут соответствовать значениям внедренных изображений в компонент ImageList1.
Далее активизируйте компонент ActionList1 в инспекторе объекта, найдите свойство Images, произведите щелчок справа от события и выберите в списке ImageList1.
Используя свойство Hint можно ввести подсказки для действий.
Событие OnUpdate возникает в промежутках между действиями. Рассмотрим некоторые события компонента ActionList. Возникновение этих событий прекращается только во время реализации события или когда пользователь ничего не делает и компьютер находится в состояния ожидания действий. Обработчик события OnUpdate может содержать какие-то настройки, подготовку ожидаемых дальнейших действий или выполнение каких-то фоновых операций.
Событие OnHint возникает в момент, когда на экране отображается ярлычок подсказки в результате того, что пользователь задержал курсор мыши над компонентом, инициализирующим событие.
Свойство компонента ActionCount
property ActionCount: Integer;
содержит число действий в списке действия.
Свойство property Actions[Index: Integer]: TContainedAction;
содержит индексированный список действий в списке действий, это свойство позволяет обратиться к нужному действию по его индексу.
Свойство property Images: TCustomImageList;
содержит список компонентов с изображениями, доступных для использования в списке действия.
ImageList представляет собой список точечных рисунков, которые могут быть отображены слева от любого действия, в списке действий редактора. Действие связано с изображением в списке изображений свойством ImageIndex.
Редактор компонента создает объекты класса TAction.
Рассмотрим его некоторые свойства.
Свойство Checked содержит значение, которое будет устанавливаться в свойствах Checked.
Свойство DisableIfNoHandler указывает, будут ли запрещены для выбора связанные компоненты, если для действия не определен обработчик OnExecute.
Cвойство Helpcontext содержит значение, которое будет устанавливаться в свойствах HelpContext.

Владимир Скуратов


(c) компьютерная газета


Компьютерная газета. Статья была опубликована в номере 47 за 2001 год в рубрике программирование :: delphi

©1997-2024 Компьютерная газета