Файлы в Delphi
В Паскале традиционно используются файлы трех типов — текстовые, типизированные и двоичные. В отличие от Бейсика и Си, где с именами открываемых файлов связываются программные числовые номера, в Паскале их заменяют переменные файлового типа. Эти переменные объявляются в разделе описания переменных :
type
PhoneRec = record
Name:string[20];
Phone:string [15];
Address:string [40];
BirthDay:TDateTime;
end;
var
ft:TextFile; {файловая переменная для текстового файла}
fb:File; {файловая переменная для двоичного файла}
fr:File of PhoneRec;
{файловая переменная для типизированного файла}
После этого в разделе исполняемых операторов имена файловых переменных с помощью процедуры AssignFile связываются с именами дисковых файлов соответствующего типа:
AssignFile(ft,'abc1.txt');
AssignFile(fb,'abc2.bin');
AssignFile(fr,'abc3.rec');
И только теперь можно приступить к процедуре открывания файлов. Не в обиду будет сказано, но авторы Паскаля здесь умудрились выбиться из общепринятой колеи и вместо четкого Open взяли на вооружение гораздо менее привычные служебные слова Reset (для файлов ввода), Rewrite (для файлов вывода) и Append (для пополнения текстовых файлов):
Reset(ft); Rewrite(ft); Append(ft);
Reset(fb[,len]); Rewrite(fb[,len]);
Reset(fr); Rewrite(fr);
Второй необязательный аргумент len, используемый при открытии двоичных файлов, устанавливает в байтах размер порции данных, которые принимают участие в процедурах обмена. По умолчанию используются блоки размером по 128 байт, но эта цифра, скорее, дань традиции Паскаля. С точки зрения оптимизации скорости обмена длина блока должна быть равной длине кластера. Однако и это не совсем точно, т.к. на время передачи данных существенно большее влияние оказывает аппаратура управления винчестером, располагающая своим собственным кэшем.
Открытые файлы любого типа закрываются с помощью процедуры CloseFile:
CloseFile(ft); CloseFile(fb); CloseFile(fr);
Для обмена с текстовыми файлами используются обычные операторы read/readln и write/writeln, первым аргументом которых являются имена переменных файлового типа:
write(ft, x1:10,x2:6);
writeln(ft,' ',x3);
........................
readln(ft,y1,y2,y3);
Чтобы очередная порция данных, записываемая в текстовый файл, была завершена признаком конца строки (символ «Возврат каретки» или пара символов «Возврат каретки» и «Перевод строки»), вывод последней (или единственной) части строки должен быть завершен оператором writeln. Кроме этого, пользователь должен позаботиться о том, чтобы числовые данные, направляемые на диск, разделялись, как минимум, одним пробелом. В цикле считывания строк из текстового файла программа может определить момент исчерпания данных по значению логической функции Eof(ft). Она принимает значение True, если между текущей позицией указателя и концом файла ничего кроме пробелов нет.
Приложение 7_01 (Delphi).
Приводимое ниже приложение осуществляет побайтовое копирование содержимого одного текстового файла в другой. Первый текстовый файл должен существовать, т.к. его имя выбирается пользователем в стандартном диалоговом окне Opendialog1. Второй файл может быть создан — такая возможность предусмотрена в диалоговом окне SaveDialog1. Процедура переписи включена в состав обработчика события OnActivate.
unit Unit1;
interface
uses
Windows,Messages,SysUtils,Variants,Classes,Graphics,Controls,Forms,
Dialogs;
type
TForm1 = class(TForm)
OpenDialog1: TOpenDialog;
SaveDialog1: TSaveDialog;
procedure FormActivate(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.FormActivate(Sender: TObject);
var
ft1, ft2: TextFile;
ch: Char;
begin
if OpenDialog1.Execute then begin
AssignFile(ft1,OpenDialog1.Filename);
Reset(ft1);
if SaveDialog1.Execute then
begin
AssignFile(ft2,SaveDialog1.Filename);
Rewrite(ft2);
while not Eof(ft1) do begin
Read(ft1,ch);
Write(ft2,ch);
end;
CloseFile(ft2);
end;
CloseFile(ft1);
end;
end;
end.
В обмене с типизированными файлами используются только операторы read и write. При этом источником или получателем данных должна быть единственная переменная типа record, имеющая такую же структуру, которая была использована при объявлении файла.
Приложение 7_02 (Delphi).
В приведенном ниже приложении на форме находится две кнопки — Button1 с надписью <Записать в файл> и Button2 с надписью <Прочитать из файла>. Щелчок по первой кнопке приводит к созданию типизированного файла с именем Poly.dat, записи которого представляют координаты вещественных точек. В обработчике этого же события координаты точки P1 записываются в файл. Щелчок по второй кнопке извлекает координаты первой точки из файла в запись P2.
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;
type
TForm1 = class(TForm)
Button1: TButton;
Button2: TButton;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
type
DPoint=record
x:double;
y:double
end;
var
Form1: TForm1;
P1,P2:DPoint;
fp:file of DPoint;
implementation
{$R *.dfm}
procedure TForm1.Button1Click(Sender: TObject);
begin
AssignFile(fp,'Poly.dat');
Rewrite(fp);
P1.x:=1;
P1.y:=2;
Write(fp,P1);
CloseFile(fp);
end;
procedure TForm1.Button2Click(Sender: TObject);
begin
AssignFile(fp,'Poly.dat');
Reset(fp);
Read(fp,P2);
CloseFile(fp);
end;
end.
При обмене с типизированным файлом допустим переход к любой существующей записи с заданным номером (записи в файле нумеруются от 0). Установка указателя файла на запись с номером nr осуществляется процедурой Seek:
Seek(fr,nr);
С двоичными файлами обмен производится блоками, размер которых установлен либо по умолчанию (128 байт), либо был объявлен в момент открывания файла. Для этой цели используются специальные операторы BlockWrite и BlockRead:
BlockWrite(fb, buf, n_block,v1);
BlockRead(fb, buf, n_block,v1);
Здесь buf — массив (обычно типа byte), в котором либо находятся данные, подготовленные для записи на диск, либо предназначенный для хранения считываемых с диска данных. Параметр n_block задает количество блоков, участвующих в обмене. В переменную v1 заносится фактическое количество записанных или считанных блоков. Несовпадение между n_block и значением v1 при чтении обычно связано с тем, что реальная длина файла не всегда кратна размеру блока. При выводе такое событие, как правило, свидетельствует об исчерпании дисковой памяти. Подобно записям в типизированных файлах блоки данных в двоичном файле тоже нумеруются от 0. И для перехода к блоку с нужным номером необходимо воспользоваться процедурой Seek.
Перечень дополнительных функций по управлению файлами в системе Delphi приведен в табл. 7.2.
Таблица 7.2
| Процедура/функция | Назначение |
| ChDir | Назначает новый текущий каталог на текущем диске |
| Eoln | Возвращает значение True, если в строке текстового файла обнаружен признак конца строки |
| Erase | Уничтожает указанный файл |
| FilePos | Возвращает номер текущей записи или текущего блока в типизированном или двоичном файле |
| FileSize | Возвращает количество записей или блоков в типизированном или двоичном файле |
| Flush | Выталкивает содержимое буфера обмена в выводной текстовый файл |
| GetDir | Возвращает имя текущего каталога на указанном логическом диске |
| IOResult | Возвращает числовой код, свидетельствующий о результате завершения предыдущей операции с дисковым файлом. При нормальном завершении IOResult=0 |
| MkDir | Создает новый подкаталог |
| Rename | Переименовывает указанный файл |
| RmDir | Удаляет пустой подкаталог |
| SeekEoln | Возвращает значение True, если между текущей позицией указателя и концом строки в текстовом файле нет значащих символов кроме пробела |
| SetTextBuf | Изменяет длину встроенного буфера у текстового файла |
| Truncate | Удаляет данные от текущей позиции указателя до конца типизированного или двоичного файла |
