11.6. Операции над файлами - Конспект лекций по информатике для специальностей 2102, 2103 Автор доц., к т. н. Каширская Е. Н

^ 11.6. Операции над файлами
Язык Паскаль не содержит встроенных операций по обработке файловых переменных. Это характерно для многих языков программирования высокого уровня. Поэтому для реализации операций над файловыми переменными базовое ядро Паскаля требует определённого интерфейса с физическим аппаратным сооружением. Этот интерфейс реализуется с помощью специальных процедур и функций.

Операции по установке связей между файловой переменной и внешним устройством или внешним файлом на магнитном носителе, т.е. операции по открытию файлов, а так же операции по «развязке» этих связей, т.е. закрытию файлов реализуются процедурами:

Assign Rewrite Close

Reset Append Flush

Связывание файловой переменной с именем файла осуществляется обращением к встроенной процедуре ASSIGN:

Assign ( файловая переменная, имя файла ).

Здесь имя файла – переменная или константа типа String. Имя должно быть написано в соответствии с правилами MS DOS, может включать путь и не должно превышать 79 символов. Если строка имени пустая, осуществляется связь со стандартным файлом ввода или вывода (как правило, консолью).

Файл становится доступен программе только после выполнения особой процедуры открытия файла. Эта процедура заключается в связывании ранее объявленной файловой переменной с именем существующего или вновь создаваемого файла, а также в указании направления обмена информации: чтение из файла или запись в него.

Примеры:

1) Установление связи с внешним файлом на магнитном носителе. В этом случае имя внешнего файла представляет собой спецификацию файла:

Assign (Namefaile,’C:\direct\tfile.dat’);

Assign (Kandy,’D:\direct\sadry\fio.dat’);

2) Установление связи программного файла с внешним устройством. Для ввода с клавиатуры, если далее следует операция считывания данных; либо вывода на экран дисплея, если далее следует операция записи данных:

Assign (inputfile,’CON’);

3) Для вывода данных на печатающее устройство (допускается подключение до трёх печатающих устройств): LPT1 (синоним PRN), LPT2 и LPT3.

Assign ( Outhut,’LPT1’ );

4) Для последующего обмена информацией по коммуникационным каналам. Смысл записи псевдофайлов COM1 (или синоним AUX) либо СОМ2 определяется конкретным внешним устройством. Например, это может быть «мышь» или графопостроитель (плотер), либо узел при сетевой связи компьютеров:

Assign ( interfile,’COM1’ );

5) Установление связи с фиктивным внешним устройством. Например, при отладке программы вывод информации блокируется, но конкретная работа программы при этом не нарушается:

Assign (myfile,’NUL’);


^ Реализация операций обмена данными

После установления связи необходима инициализация этой связи, т.е., как принято говорить, необходимо открытие файла. Иницировать файл – означает указать для этого файла направление передачи данных. В Паскале можно открыть файл для двух видов взаимодействия: чтения и записи.

Эта операция в общем случае выполняется следующими процедурами:

Reset (файловая переменная, размер записи);

Reset (файловая переменная);

Rewrite (файловая переменная);

Rewrite (файловая переменная, размер записи);

Append (файловая переменная);


^ Основные процедуры обработки файлов

Reset (F) – подготовка чтения файла F. При этом указатель позиции помещается в начало файла. Если файл не пустой, то переменной F присваивается значение его первого компонента, а функция eof (F) = false. Параметр «размер записи» указывается лишь в случае обработки нетипизированных файлов. В результате обработки процедуры Reset, если соответствующий файл обнаружен, текущий указатель устанавливается в начале файла, т.е. на нулевом элементе файла. Если же внешний файл не обнаружен, то вырабатывается условие ошибки. Оператор процедуры reset(f) переводит файл f в режим чтения и устанавливает окно на первую позицию файла. Оператор процедуры read(f,v) присваивает переменной v значение текущей компоненты из файла f и передвигает окно на следующую позицию. Процедура reset может применятся к одному и тому же файлу несколько раз и при этом содержимое его не изменяется.

Rewrite (F) – подготовка записи в файл. Текущее значение файловой переменной F становится равным emply (пустой). Функция eof (F) = true. Может записывать новый файл. Оператор процедуры rewrite(f) устанавливает файл в режим записи, если раньше в этот файл были записаны какие-то данные, то они теряются. Оператор процедуры write(f,x) записывает в файл f очередную компоненту x, после чего окно сдвигается на следующую позицию. Общий вид оператора подготовки запист:

Rewrite (файловая переменная, [имя файла]);

Если внешнее имя файла опущено при открытии файла для записи, то файловая переменная трактуется как временный файл, который по окончанию работы программы ликвидируется. Параметр. «размер записи» указывается лишь в случае нетипизированного файла. В результате обработки процедуры ReWrite, если соответствующий файл обнаружен, текущий указатель устанавливается в начале файла, на место нулевого элемента записывается «символ конца файла». Другими словами, процедура rewrite очищает содержимое файла, а текущий указатель устанавливается в позицию готовности записи нулевого элемента.

Непосредственные операции ввода–вывода выполняются процедурами read и write. Обращения к этим процедурам:

Read (файловая переменная, выражение);

Write (файловая переменная, выражение);

После открытия на запись файл считается пустым, а указатель устанавливается на начало; в этот файл затем можно последовательно заносить информацию из буферной переменой при помощи процедуры write:

write (файловая переменная);

Если файл с таким именем уже существует, то вся информация, хранившаяся ранее в этом файле, становится недоступной. Процедура Write записывает в файл очередной компонент и переставляет указатель на свободное место. Таким образом, число компонентов файла увеличивается на единицу.

В принципе все операции создания и чтения последовательного файла можно сформировать из приведённых простых процедур и стандартной функции eof. На практике же часто полезно совмещать перемещение по файлу с доступом к буферной переменной. Поэтому введём две новые процедуры Read и Write следующим образом:

Read (F,X), где Х – некоторая переменная.

Write (F,Y), где Y – некоторое выражение.

Read и Write – специальные процедуры, распространённые для работы с переменным числом параметров (Х1,Х2,…,ХN – переменные, а Y1,Y2,…,YN – выражения).

Обращение к функции Read (F,X1,…,XN) эквивалентно конструкции

begin

Read (F,X1);

Read (F,X2);

…………….

Read (F,XN)

end;

к функции Write (F,Y1,Y2,…,YN) - эквивалентно конструкции

begin

Write (F,Y1);

Write (F,Y2);

…………….

Write (F,YN)

end;

Если элементы в файле хранятся по строкам, то для определения конца строки файла используется оператор цикла

While Not EOLN (имя) Do,

а для перехода на новую строку файла – оператор Readln (имя).

^ Чтение файла – это ввод данных из внешнего файла, находящегося на диске, в оперативную память машины. Данные внешнего файла становятся доступными программе. Процедура Read предназначена для чтения данных из внешнего файла, связанного с файловой переменной, в программу. Выражение содержит список переменных, в которые помещаются считываемые элементы файла. Тип этих переменных должен совпадать с баз. типом элементов файла.

Для чтения файла необходимо выполнить следующие действия:

открыть файл для чтения ( процедура Reset );

ввести данные файла в программу ( процедура Read );

закрыть файл для чтения ( процедура Close )

Общая форма чтения файла:

Reset ( файловая переменная, [имя файла] );

……………..

Read ( файловая переменная, параметры );

……………..

Close ( файловая переменная );

Читать файл можно только с начала, предварительно открыв его на чтение процедурой Reset.

^ Порядок выполнения операций чтения.

Начиная с текущей позиции, то есть с позиции текущего указателя, последовательно считываются элементы файла и засылаются в поля переменных, указанных в выражении. После чтения очередного элемента текущий указатель смещается на начало следующего элемента файла. При достижении текущим указателем позиции, не содержащей элементов файла, завершается операция чтения, то есть достигается конец файла. Возникновение этой ситуации можно проверить с помощью встроенной функции EOF.

Пример. При открытии файла с именем С для чтения соответствующая буферная переменная принимает значение первой записи файла С. Если файл пуст, то EOF (C) = True, а значение буферной переменной не определено. Для чтения очередной записи из файла С необходимо выполнить процедуру Read (C). При этом считанная запись станет доступной через буферную переменную. При окончании записи элементов в файл С его необходимо закрыть при помощи процедуры Close (C). При этом файл С сохраняется на внешнем носителе, если при его открытии на запись было указано внешнее имя.

Файловая переменная логически связана с внешним устройством. Если внешнее имя файла опущено при открытии файла для чтения, то файловая переменная трактуется как временный файл, созданный ранее в этой же программе.

^ Запись в файл. Процедура Write предназначена для записи во внешний файл данных из программы. Имя внешнего файла также с помощью процедуры Assign связанно с файловой переменной. Тип переменных, из полей которых записываются данные в файл, должны совпадать с баз. типом элементов файла.

^ Порядок выполнения операции записи.

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

Открыть один и тот же файл для чтения и для записи одновременно нельзя, поэтому открыть для чтения можно только предварительно закрытый файл.

Турбо – Паскаль допускает к файлам, открытым с помощью процедуры Reset (то есть для чтения информации), обращаться с помощью процедуры Write (то есть только для записи информации). Такая возможность позволяет легко обновлять ранее созданные файлы и при необходимости расширять их.

Встроенная процедура rewrite инициирует запись информации в файл.

Пример. Для записи в файл С очередного компонента, находящегося в буферной переменной, необходимо выполнить процедуру Write (C).

Процедура Append применяется для открытия файла, который подвергается обработке операциями записи данных. При этом текущий указатель устанавливается в конце файла, то есть в позицию для записи следующего элемента. Другими словами, процедура Append не очищает содержимого файла. Встроенная процедура Append (файловая переменная) инициирует запись в ранее существовавший текстовый файл для его расширения – указатель файла устанавливается в его конец.

Если же соответствующие файлы на внешнем носителе не обнаружены, то процедуры Append и ReWrite открывают новый файл с указанным именем, соответствующим заданной файловой переменной.

Если работа с данным файлом завершена, то рекомендуется выполнить операцию закрытия файла. Она реализуется с помощью процедуры

Close (файловая переменная).

Для применения операции обработки файла после его закрытия не нужно выполнять повторную связь файловой переменной с внешним файлом с помощью процедуры Assign, эта связь сохраняется до конца работы программы.

Рассмотрим процедуры и функции, которые можно использовать с файлами любого вида. Специфику работы с типизированными, текстовыми и нетипизированными файлами рассмотрим потом отдельно.

Процедура Close – закрывает файл, однако связь файловой переменной с именем файла, установленная ранее процедурой Assign, сохраняется. При создании нового или расширении старого файла процедура обеспечивает сохранение в файле всех новых записей и регистрацию файла в каталоге. Функции процедуры Close выполняются автоматически по отношению ко всем открытым файлам при нормальном завершении программы. Поскольку связь файла с файловой переменной сохраняется, файл можно повторно открыть без дополнительного использования процедуры Assign.

Процедура Rename (файловая переменная, новое имя). Переименовывает файл. Перед выполнением процедуры Rename необходимо закрыть файл, если он ранее был открыт процедурами Reset, ReWrite, Append. Внешний файл, с которым связана файловая переменная, получает новое имя, заданное параметром «новое имя». Этот параметр по своим характеристикам аналогичен параметру «имя файла» в процедуре Assign.

Процедура Erase (файловая переменная) уничтожает файл.

Erase (файловая переменная).

Перед выполнением процедуры необходимо закрыть файл, если он ранее был открыт процедурами Reset, ReWrite или Append.

Процедура Flush (файловая переменная). Поскольку обмены с файлами реализуются через некоторый внутренний буфер в оперативной памяти, то в процессе обработки информации могут возникать ситуации задержки данных, то есть «застревание» информации в буфере. Если же в процессе обработки информации не требуется пополнять буфер, то есть считывать следующий элемент, либо разбивать находящиеся в буфере данные на порядки, то с помощью процедуры Flash (файловая переменная) выполняется принудительный сброс информации при записи и очистка буфера. Процедура Flush игнорируется, если файл был инициирован для чтения процедурой Reset. Ценность этой процедуры сомнительна, так как все её функции реализуются процедурой Close, при выполнении которой закрытие файла автоматически сопровождается ликвидацией соответствующего буфера.

При завершении программы автоматически выполняется закрытие всех открытых в программе файлов.

Процедура ChDir (путь) – излагает текущий каталог (директорию). Здесь «путь» – строковое выражение, содержащее путь к установленному по умолчанию каталогу. Параметр. «путь» может быть только типа String. Таким образом, ChDir устанавливает новый текущий каталог, путь к которому находится в процедуре «путь».

Процедура GetDir (устройство, каталог) позволяет определить имя текущего каталога (каталога по умолчанию). Здесь «устройство» - выражение типа Word, содержащее номер устройства:

0 – устройство по умолчанию,

1 – диск А,

2 – диск В и т. д.

Здесь «каталог» - переменная типа String, которая определяет путь к текущему каталогу на указанном диске.

Процедура MkDir (каталог) создаёт новый каталог на указанном диске. Здесь «каталог» - выражение типа String, задающее путь к каталогу. Последним именем в пути, то есть именем вновь создаваемого каталога, не может быть имя уже существующего каталога.

Процедура RmDir (каталог) удаляет каталог. Удалённый каталог должен быть пустым, то есть не содержать файлов или имён каталогов нижнего уровня.

Функция IOResult : Word возвращает признак последней операции ввод – вывод. Если операция завершилась успешно, функция возвращает ноль. Эта функция становится доступной только при отключённом автоконтроле ошибок ввода – вывода. Директива компилятора { $1-} отключает, а { $1+} включает автоконтроль. Если автоконтроль отключён и операция ввода – вывода привела к возникновению ошибки, устанавливается флаг ошибки и все последующие обращения к вводу – выводу блокируются, пока не будет вызвана функция IOResult.

Ряд полезных процедур и функций становится доступным при использовании библиотечного модуля DOS, входящего в стандартную библиотеку TurboTPL. Доступ к ним возможен только после объявления USES DOS в начале программы. Вот какие это функции и процедуры.

Функция DiskFree (диск) : Longint. Возвращает объём в байтах свободного пространства на указанном диске. В этой функции «диск» - номер диска:

0 – устройство по умолчанию,

1 – диск А,

2 – диск В и т. д.

Функция возвращает значение -1, если указан номер несущего диска.

Функция DiskSize (диск): Longint. Возвращает полный объём диска в байтах ( -1, если указан номер несуществующего диска).

Операции по непосредственному обмену данными между программой, интерфейс которой представляется файловой переменной и внешними данными (или внешними устройствами), представляющими собой физические средства регистрации файлов, реализуются процедурами:

Read Write

Readln Writeln

BlockRead BlockWrite

Пример. Работа с файлом FIZAP.

В файл сначала заносятся три записи, каждая из которых представляет собой совокупность двух полей. Первое поле (FIO) содержит фамилию, а второе поле (GOD) - год рождения. Ввод исходной информации осуществляется с терминала. Затем этот файл закрывается и вновь открывается только уже на чтение, после чего из файла считываются три записи и выводятся на терминал. По окончанию работы программы файл FIZAP сохраняется.

Внешнее имя РР71.dat

Program PP71;

Type ZAP = Record

FIO : Array [1…10] of Char;

GOD: integer

end; {of record}

F = File;

Var FIZAP: F;

A, B : ZAP;

J, I : integer;

begin Assign (FIZAP, `C: \ Program \ t – pas \ pp71.dat);

ReWrite (FIZAP, 12);

For Y : = 1 to 3 do

Begin Write (`=>`);

For I = 1 to 10 do

read (B. FIO [I]);

Readln (B. God);

BlockWrite (FIZAP, B, 1)

end;

close (FIZAP);

Reset (FIZAP, 12);

For J: = 1 to 3 do

begin BlockReadln (FIZAP, A, 1);

Writeln (J : 2, `-ая запись `, A. FIO, A. GOD: 5);

end

end.

Протокол работы программы:

Иванов 1967

Петров 1970

Сидоров 1968

1 – ая запись Иванов 1967

2 – ая запись Петров 1970

3 – ая запись Сидоров 1968

Пример. Программа формирует файл и сохраняет его на внешнем носителе, что обеспечивается заданием внешнего имени PP74.dat при открытии файла на запись. Ввод исходной информации во внешний файл в программе осуществляется до тех пор, пока не будет введена фамилия, состоящая из десяти звёздочек (признак конца ввода). Это сделано для того, чтобы пользователю не надо было предварительно подсчитывать количество вводимых записей.

Program PP74;

Type ZAP = Record

FIO : Array [1…10] of Char;

GOD: integer

end; {of record}

F = File;

Var FIZAP: F;

A : ZAP;

I : integer;

begin Assign (FIZAP, `C: \ t – pas \ pp74.dat);

ReWrite (FIZAP, 12);

Repeat

Write (`=>`);

For I = 1 to 10 do

read (A. FIO [I]);

Readln (A. God);

BlockWrite (FIZAP, A, 1)

Until A . FIO = `**********`;

close (FIZAP);

Reset (FIZAP, 12);

I: = 1;

Repeat BlockRead (FIZAP, A, 1);

Writeln (I : 2, `-ая запись `, A. FIO, A. GOD: 5);

I : = I+1

Until A . FIO = `**** `;

end.

Протокол работы программы:

Иванов 1966

Петров 1970

Сидоров 1972

Пушкин 1968

1 – ая запись

2 – ая запись

и т. д.

Пример. В программе из внешнего файла с именем PP75.dat удаляются все записи, соответствующие людям, родившимся до 1970 года. Для этого используется рабочий файл с внешним именем `PPR.dat`, в который сначала последовательно переписываются из внешнего файла все оставляемые записи, затем внешний файл открывается на запись, рабочий файл – на чтение и всё содержимое рабочего файла переписывается во внешний файл. При этом для контроля работы программы оставляемые записи выдаются на терминал.

Program PP75;

Type ZAP = Record

FIO : Array [1…10] of Char;

GOD: integer

end; {of record}

F = File;

Var FIZAP, RB: FPK;

A : ZAP;

I : integer;

{Ввод данных в файл FIZAP}

begin Assign (FIZAP, `C: \ t – pas \ pp75.dat);

ReWrite (FIZAP, 12);

Repeat

Write (`=>`);

For I = 1 to 10 do

read (A. FIO [I]);

Readln (A. God);

BlockWrite (FIZAP, A, 1)

Until A . FIO = `**********`; {здесь год должен быть >1970}

close (FIZAP);

{контрольный вывод содержимого обрабатываемого файла FIZAP}

Writeln;

Writeln (`обрабатываемый файл :`);

Reset (FIZAP, 12);

I: = 1;

Repeat BlockRead (FIZAP, A, 1);

Writeln (I : 2, `-ая запись `, A. FIO, A. GOD: 5);

I : = I+1

Until A . FIO = `**********`;

close (FIZAP);

{Перепись из обработанного файла FIZAP в рабочий файл RB людей, родившихся не ранее 1970 года}

Reset (FIZAP, 12);

Assign (RB, `C: \ Language\ t – pas \ pp75.dat);

ReWrite (RB, 12);

Repeat

BlockRead (FIZAP, A, 1);

If A . GOD >= 1970 Chen BlockWrite (RB, A, 1)

Until A . FIO = `**********`;

close (RB);

close (FIZAP);

{ контрольный вывод содержимого обрабатываемого файла RB}

Writeln;

Writeln (`рабочий файл :`);

Reset (RB, 12);

I: = 1;

Repeat BlockRead (RB, A, 1);

Writeln (I : 2, `-ая запись `, A. FIO, A. GOD: 5);

I : = I+1

Until A . FIO = `**********`;

close (RB);

{Перепись из рабочего файла RB в обрабатываемый файл FIZAP}

Reset (RB, 12);

ReWrite (FIZAP, 12);

Repeat

BlockRead (RB, A, 1);

BlockWrite (FIZAP, A, 1)

Until A . F1O = `**********`;

close (RB);

close (FIZAP);

{ контрольный вывод содержимого обрабатываемого файла}

Writeln;

Writeln (`обработанный файл :`);

Reset (FIZAP, 12);

I: = 1;

Repeat BlockRead (FIZAP, A, 1);

Writeln (I : 2, `-ая запись `, A. FIO, A. GOD: 5);

I : = I+1

Until A . FIO = `**********`;

close (FIZAP);

Writeln (`ok`)

end.


Для добавления записей в конец не существующего файла необходимо воспользоваться промежуточным файлом. Сначала скопировать всё содержимое обрабатываемого файла в промежуточный файл, записать в конец добавляемые записи, затем открыть на запись обрабатываемый файл и переписать в него всё содержимое промежуточного файла.

Для добавления записей в конец существующего файла необходимо также воспользоваться промежуточным файлом. Сначала скопировать всё содержимое обрабатываемого файла в промежуточный файл, записать в конец добавляемые записи, затем открыть на запись обрабатываемый файл и переписать в него всё содержимое промежуточного файла.

Программа записи информации о товарах во внешний файл по сф-ре. может быть аналогичной программе РР74. Разница будет заключаться в названии и количестве полей каждой записи, а также в форме задания вешнего имени файла в операторе ReWrite.

Пример. Программа обеспечивает добавление во внешний упорядоченный файл одной записи. Она может быть принята за основу при разработке программы, которая добавляет во внешний упорядоченный файл М записей. Для этого достаточно повторить в цикле М раз те действия, которые производились при добавлении одной записи.

Program Z3;

Type ZAP = Record

NOV : Array [1…10] of Char;

Cena : integer

end; {of record}

Tovar = File of ZAP;

Var Nov, Star: Tovar;

B : ZAP;

I : integer;

Begin

(*ввод с терминала полей новой записи*)

Write (`=>`);

For I := 1 to 10 do

read (B. Nazv [I]);

Readln (B. Cena);

(*открытие файлов*)

Reset (Star, Star.dat);

ReWrite (Nov, Nov.dat);

(*вставка новой записи*)

While условие окончания ввода записей do

Операторы ввода записей

Close (Nov):

(*перепись данных из нового файла в старый и их печать*)

Reset (Nov, Nov.dat);

ReWrite (Star, Star.dat);

Repeat

Операторы присваивания значений записей нового файла записям старого файла.

Writeln (B. Nazv, B. Cena) (*вывод на терминал*)

Until B. Nazv = `**********`;

Close (Star)

end.

7280525080949491.html
7280665703230825.html
7280754052444503.html
7280920424870607.html
7281041475035156.html