Пропустить навигацию.
Главная

Файлы в 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 Удаляет данные от текущей позиции указателя до конца типизированного или двоичного файла