ТЕМА №10: ФАЙЛЫ. ТИПИЗИРОВАННЫЕ ФАЙЛЫ. ТЕКСТОВЫЕ ФАЙЛЫ.

Основные понятия

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

Файлы – это массив переменной длины неограниченного размера.

Файл может находиться в составе другой сложной структуры, но не должен входить в другой файл.

Отличие файла от массива:

А) размещение на внешнем носителе;

Б) длина файла не задается;

В) место элемента не определяется индексом.

Круглая лента лицом вниз: ФАЙЛЫ
 

Багетная рамка: Типизированные



(в описании присутствует указание типа) 

Багетная рамка: Текстовые



(компонентами являются данные символьного типа)
Багетная рамка: Не типизированные



 (последовательность байтов, без конкретизации структуры)
 

Для обозначения файла и работе с ним используется файловая переменная (ФП).

Файловая переменная - это переменная, используемая в программах для обозначения файла и обращения к нему.

Особенности файловой переменной:

Ей нельзя присваивать какие-либо значения

Она не может участвовать в логических операциях

Она не может входить в математические выражения

Объявление файловой переменной

Файл объявляется в разделе описания переменных с указанием типа элементов файла.

Тип файла

Описание файла

Типизированный

Var F1: file of integer;

F2: file of char;

Не типизированный

Var F3: file;

Текстовый

Var F: text;

РАБОТА С ФАЙЛОМ

А) ЗАПИСЬ В ФАЙЛ

Связываем файл (можно не существующий) с именем Name с файловой переменной (ФП)

Assign(ФП, ‘Name’);

Открываем файл для записи

Rewrite( ФП );

Записываем данные в файл

Write(ФП, Данные);

Writeln(ФП, Данные); - для текстовых

Закрываем файл

Close (ФП);

Б) ЧТЕНИЕ ИЗ ФАЙЛА

НЕ нашли? Не то? Что вы ищете?

Связываем файл (можно не существующий) с именем Name с файловой переменной (ФП)

Assign(ФП, ‘Name’);

Открываем файл для чтения (указатель устанавливается на первый элемент)

Reset( ФП );

Читаем данные из файла в переменные и передвигаем указатель файла вперёд.

Read(ФП, Переменные);

Readln(ФП, Переменные); - для текстовых

Закрываем файл

Close (ФП);

При работе с файлом используется понятие указателя или индекса файла, т. е. положение магнитной головки в определенном месте файла.

ОПРЕДЕЛЕНИЕ ДЛИНЫ ТЕКСТОВЫХ ФАЙЛОВ

В Паскале нет команды, которая бы определяла количество строк, записанных в текстовый файл. Однако есть функция, которая подсказывает момент, когда указатель файла достиг последней строки - EOF (End Of File)

EOF ( ФП ) – функция подтверждающая

достижение конца текстового файла

Если конец файла достигнут, то EOF ( ФП ) равняется true.

Если конец файла не достигнут, то EOF ( ФП ) равняется false.

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

Var f: text; N:integer; s:string;

Begin

Assign (f, ‘c:\MyText. txt’);

Reset (f);

N:=0;

While Eof(f)=false do {можно записать эту строчку короче: While not Eof(f) do}

Begin

Readln(f, s);

N:=N+1;

End;

Close (f);

Writeln ('В файле c:\MyText. txt ', N, ' строк');

End.

ОПРЕДЕЛЕНИЕ ДЛИНЫ ДВОИЧНОГО ФАЙЛА

Для двоичных типизированных файлов применим способ, который используется при чтении текстовых файлов. Функция EOF работает одинаково и для текстовых и для двоичных фалов.

Кроме того, при работе с двоичными файлами можно пользоваться функцией FileSize, которая определяет длину двоичного файла.

FileSize ( ФП ) – функция, возвращающая длину двоичного файла

Программа, читающая все числа из двоичного целочисленного файла и находящая их сумму:

Var f: file of integer;

Summ, i, T :integer;

Begin

Assign (f, ‘c:\MyFile. int’);

Reset (f);

Summ:=0;

For i:=1 to Filesize(f) do {можно использовать другой цикл: While not Eof(f) do}

Begin

Read(f, T);

Summ:=Summ + T;

End;

Writeln ('Сумма чисел, в файле c:\MyFile. int равна ', Summ);

Writeln ('Длина файла c:\MyFile. int ', FileSize(f), ' чисел');

Close (f);

End.

ПЕРЕМЕЩЕНИЕ ПО ДВОИЧНОМУ ФАЙЛУ

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

SEEK ( ФП, Позиция) – перемещает указатель

в заданную позицию файла

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

Var f: file of real; {объявляем файловую переменную для вещественного файла}

Poz, N :integer;

R, Null: real;

Begin

Assign (f, ‘c:\MyRealFile. rlf’); {связываем файловую переменную с файлом}

Reset (f); {открываем файл для чтения и записи}

N:= FileSize(f); {определим количество чисел в файле}

Repeat {начало цикла}

Writeln('В файле ‘, N, ‘ чисел’);

Writeln('Введите номер числа, которое надо перенести в конец файла?’);

Readln(Poz);

Until (Poz>=0) and (Poz<=N) {выход из цикла, только если в данном файле такая позиция существует}

Seek(f, Poz); {позиционируем указатель файла на заданную позицию}

Read(f, R); {читаем число из заданной позиции файла в переменную R, указатель перемещается на одну позицию вперёд}

Seek(f, Poz); {возвращаем указатель в заданную позицию}

Null:=0;

Write(f, Null); {обнуляем число в котором установлен указатель}

Seek(f, N); {перемещаем указатель в конец файла}

Write(f, R); {записываем число из переменной R в конец файла}

Close (f);

End.

УМЕНЬШЕНИЕ ДВОИЧНЫХ ФАЙЛОВ

Чтобы сократить двоичный файл, надо установить указатель файла в то место, дальше которого расположена лишняя информация и отсечь лишнюю часть процедурой Truncate.

Truncate ( ФП )процедура, отсекающая данные, расположенные после указателя файла

Программа, оставляющая в двоичном файле только первые 10 чисел:

Var f: file of real; {объявляем файловую переменную}

Begin

Assign (f, ‘c:\MyRealFile. rlf’); {связываем файловую переменную с файлом}

Reset (f); {открываем файл для чтения и записи}

Seek(f, 10); {позиционируем указатель файла на заданную позицию}

Truncate (f); {отсекаем от файла всё, что расположено дальше указателя файла}

Close (f);

End.

ДОБАВЛЕНИЕ ИНФОРМАЦИИ В ТЕКСТОВЫЕ ФАЙЛЫ

К сожалению, не существует возможности при работе с текстовыми файлами вставлять какую-либо информацию в середину или в начало файла. Единственное изменение файла, которое возможно – это возможность дописать строчки в конец файла. Для этого, файл должен быть открыт к добавлению.

Append ( ФП ) – процедура, открывающая текстовый файл

для добавления строк

Программа, дописывающая в конец текстового файла две строки:

Var FT: text; s: string;

Begin

Assign (FT, ‘q. txt’);

Append (FT);

S:=’Первая добавленная строка’; Writeln (FT, S);

S:=’Вторая добавленная строка’; Writeln (FT, S);

Close (FT);

End.

ПЕРЕИМЕНОВАНИЕ, ПЕРЕНОС ФАЙЛА

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

Поэтому в Паскале одна и та же команда осуществляет и переименование файла, и перенос файла между каталогами.

ReName ( ФП, Новое_название_файла )процедура, переименовывающая файл и переносящая его в каталог,

указанный в Новом названии файла.

Команда Rename работает только с закрытыми (или ещё не открытыми) файлами. Поэтому перед её применением не надо открывать файл для чтения, записи или добавления данных. Либо, если файл уже открыт его следует предварительно закрыть.

Программа, должна дать файлу ‘q1.txt’ новое имя, которое введёт пользователь, и перенести файл ‘q2.txt’ в каталог ‘c:\Document\’.

Var FT: text; s: string;

Begin

Assign (FT, ‘q1.txt’); { связываем файловую переменную с файлом }

Writeln (‘Введите новое имя для файла q1.txt’);

Readln(s); { читаем с клавиатуры новое имя файла в переменную s}

Rename (FT, s); { переименовываем файл}

Assign (FT, ‘q2.txt’); { связываем файловую переменную со вторым файлом }

Rename (FT, ‘c:\Document\q2.txt’); { переносим файл в заданный каталог с тем же именем}

End.

Для переноса файла на другой диск необходимо скопировать файл, после чего удалить его на прежнем месте

КОПИРОВАНИЕ И УДАЛЕНИЕ ФАЙЛА

Копирование: Чтобы скопировать файл необходимо прочитать все записи одного файла и записать их во вновь созданный файл.

Удаление: Чтобы удалить файл достаточно применить к файловой переменной (связанной с закрытым файлом) процедуру Erase.

ERASE ( ФП )процедура, удаляющая файл, связанный с файловой переменной.

Программа копирует файл с диска 'C' на диcк ‘D’и удаляет оригинал с диска 'C' (фактически программа переносит файл с одного диска на другой)

Var f1, f2: file of byte;

b :byte;

Begin

Assign (f1, ‘c:\MyFile. int’); Reset (f1); {открываем для чтения файл образец}

Assign (f2, ‘d:\MyFile. int’); Rewrite (f2); {создаём файл на диске D}

While not Eof(f1) do

Begin

Read (f1, b); {читаем данные из файла оригинала}

Write (f2, b); {записываем данные в новый фал}

End;

Close (f1); {закрываем файла образец, перед удалением файл должен быть обязательно удалён}

Close (f2); {закрываем новый файл}

Erase (f1); {удаляем файл}

End.

РАБОТА С КАТАЛОГАМИ

MkDir (Имя каталога) – процедура создаёт новый каталог

(Если каталог с таким именем существует, то возникнет ошибка)

RmDir (Имя каталога) – процедура удаляет каталог

(Удалить можно только пустой каталог)

ChDir (Имя каталога) – процедура изменяет текущий каталог

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

Для переименования каталога необходимо:

а) Создать новый каталог

б) Перенести туда все файлы

в) Удалить старый каталог

Программа переименовывает каталог 'c:\Cat\', в котором расположено два файла 'q1.txt' и 'q2.ini', в каталог 'c:\CatNew\’ и делает каталог текущим.

Var f1,f2: file of byte; b :byte;

Begin

MkDir('c:\CatNew'); {создаём новый каталог}

{копируем в новый каталок файл q1.txt}

Assign (f1, ‘c:\Cat\q1.txt’); Reset (f1);

Assign (f2, ‘c:\CatNew\q1.txt’); Rewrite (f2);

While not Eof(f1) do

Begin Read (f1, b); Write (f2, b); End;

Close (f1); Close (f2); Erase (f1);

{копируем в новый каталок файл q2.ini}

Assign (f1, ‘c:\Cat\q2.ini’); Reset (f1);

Assign (f2, ‘c:\CatNew\q2.ini’); Rewrite (f2);

While not Eof(f1) do

Begin Read (f1, b); Write (f2, b); End;

Close (f1); Close (f2); Erase (f1);

RmDir (‘c:\Cat’); {удаляем старый каталог}

ChDir (‘c:\CatNew’); {делаем новый каталог текущим}

End.

Поиск файлов

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

Для поиска файлов существуют две процедуры, расположенные в модуле WinDos:

FindFirst (Маска, Флаг, Приёмник_информации) – ищет первый файл, который соответствует «маске» и «флагу», в случае обнаружения передаёт данные о найденном файле (каталоге) в переменную типа TSearchRec («приёмник информации»)

FindNext (Приёмник_информации) – ищет следующий файл, соответствующий условиям, поставленным в процедуре FindFirst, в случае обнаружения, передаёт данные о найденном файле (каталоге) в переменную типа TSearchRec («приёмник информации»)

Модуль WinDos содержит, так же переменную DosError, которая остаётся равной нулю до тех пор, пока команды поиска обнаруживают файл, соответствующий условию поиска. Если команды поиска не обнаружили файлы, соответствующие условию, то переменная

Маска поиска – строка с именем искомого файла или каталога. Кроме обычных символов маска может содержать «*» и «?».

* - значит, что в искомом файле на данном месте может присутствовать любое количество любых символов;

? – значит, что в искомом файле на данном месте может присутствовать один любой символ.

Примеры масок:

'*.*’ – любой файл с любым расширением

'quest.*' – файл с название 'quest' и любым расширением

'*.txt' – файл с любым названием и с расширением 'txt'

'qust?.txt' – файл с расширением ‘txt’, содержащий в названии 5 букв первые 4 из которых ‘qust’, а 5-ый символ любой

'qust*.txt' - файл с расширением ‘txt’, первые четыре буквы которого ‘qust’, количество следующих букв не ограниченно

'quest.txt’ – файл с названием 'quest' и расширением 'txt'

Флаг поиска - набор специальных констант соединённых оператором OR.

Можно вместо констант использовать число, равное сумме чисел с соответствующими константами

Флаг

Тип файла

Число

faReadOnly

Искать с атрибутом «Только для чтения»

1

faHidden

Искать с атрибутом «Скрытый»

2

faSysFile

Искать с атрибутом «Системный»

4

faVolumeID

Возвратить идентификатор носителя

8

faDirectory

Возвращать информацию о каталогах

16

faArchive

Искать с атрибутом «Архивный»

32

faAnyFile

Включить все предыдущие флаги

63

Примеры флагов:

·  faReadOnly or FaHidden – 3 -ищутся файлы, у которых есть атрибут «скрытый» или «только для чтения»

·  faDirectoty or FaSysFile - 20 – ищутся каталоги и файлы, у которых установлен атрибут «Системный»

Приёмник информации – переменная типа TSearchRec, которая будет содержать данные о найденном файле

Тип TSearchRec описан в модуле WinDos и не требует предварительного описания программистом. Данный тип – это запись следующего вида:

Type TSearchRec = Record

Fill: Array [1..21] of byte; {Системный параметр, нами не используется}

Attr: Byte; {Параметр, содержащий данные о флаге файла}

Time: LongInt; {Время создания файла}

Size: LongInt; {Размер файла в байтах}

Name: Array [1..12] of Char; {Имя файла}

End;

Допустим у нас есть переменная SR, которая имеет тип TSearchRec. После использования её в команде FindFirst в ней окажется информация о найденном файле (каталоге.)

Информация об имени файла попадёт в SR. Name, о размере файла в SR. Size, а чтобы определить является ли файл системным надо соединить значение SR. Attr с константой FaSysFile оператором And. Файл системный, если результат больше нуля.

Пример:

IF Sr. Attr and FaSysFile > 0 THEN Writeln ('Системный’);

Программа ищет в каталоге 'c:\Doc' все файлы с расширением 'txt'. И выводит на экран название тех, размер которых больше 3000 байт.

Uses Dos, crt, WinDos;

Var SR: TSearchRec; {Описываем переменную в которой будем хранить информацию о найденных файлах}

begin

clrscr; ChDir('c:\Doc'); {Меняем текущий каталог}

FindFirst('*.txt',faAnyFile, SR); {Ищем в текущем каталоге первый файл с расширением 'txt’ и любым набором флагов, результат в переменную SR}

while DosError=0 do {выполняем цикл пока файлы находятся}

begin

if SR. Size > 3000 {если размер файла более 3000 байт}

then writeln(SR. Name); {Выводим имя найденного файла на экран}

FindNext(SR); {Ищем следующий файл}

end;

readkey;

end.

Программа ищет все каталоги, размещённые на диске в корневом каталоге диска «С» и выводит перечень каталогов в файл 'c:\info.txt’ и на экран (Корневой каталог диска «С»– это каталог 'c:\').

Uses Dos, crt, WinDos;

Var SR: TSearchRec; f:text;

begin

Clrscr; Assign (f, 'c:\info. txt'); Rewrite(f);

ChDir('c:\'); {Переходим в корневой каталог}

FindFirst('*',faDirectory, SR); {Ищем файл без расширений включая каталоги }

While DosError=0 do {выполняем цикл пока файлы находятся}

begin

if SR. Attr and faDirectory>0 then {если файл имеет атрибут «Каталог»}

begin

Writeln (SR. Name); {выводим имя файл на экран}

Writeln (f, Sr. Name); {выводим имя файл в файл 'c:\info. txt'}

End;

FindNext(SR); {Ищем следующий файл}

end;

Close(f);

readkey;

end.

Процедуры при работе с файловыми переменными

Процедура

Назначение

Замечание

Assign(f, ‘name’)

Связывает файловую переменную с конкретным файлом (привязывает переменную к имени файла). Ставится перед первым использованием файловой переменной.

Можно имя файла ’name’ задавать через строковую переменную (S): Assign(f, S)

Reset(f)

Открывает существующий файл и устанавливает указатель на начало записи.

Для любых файлов

Rewrite(f)

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

Для любых файлов

Close(f)

Закрывает открытый файл

Для любых файлов

Erase(f)

Стирает предварительно закрытый файл

Для любых файлов

Rename(f, f1)

Переименовывает файл f в файл f1. Файл f должен быть предварительно закрыт

Для любых файлов

Read(f, v1,…vn)

Считывает записи из файла f в переменные v1, ..vn

Для типизированных и нетипизированных файлов

Write(f, v1,…vn)

Записывает в файл f значения переменных v1,…vn

Для типизированных и нетипизированных файлов

Readln(f, v1,..vn)

Считывает записи из файла f в переменные v1, ..vn

в типизированных файлах недопустимо

Writeln(f, v1,.vn)

Записывает в файл f значения переменных v1,..vn

в типизированных файлах недопустимо

Append(f)

Открывает файл и устанавливает указатель на метку конца файла

Применяется для добавления записей

seek(f, n)

Устанавливает указатель на запись с номером n

truncate(f)

Отсекает все записи, находящиеся после указателя и в этой позиции записывает метку конца файла.

Функции при работе с файловыми переменными

Процедура

Назначение

Замечание

EOF(f)

Получение сведений о конце файла True, если указатель в конце файла, иначе - False

Логическая функция.

Eoln(f)

True, если указатель на метке конца строки, иначе - False

Логическая функция. Для текстовых файлов

N:=filesize(F);

Определение количества записей в файле

N:=filepos(f)

Выдает номер записи, на которую указывает указатель записи. Первая запись имеет номер 0.

Примеры программ

ЗАДАЧА 1: Написать программу, записывающую в текстовый файл данные об авторе и 20-ть случайных цифр

var f:text;

r, i:integer;

s:string;

begin

randomize; {настраиваем генератор случайных чисел}

s:='Denis'; {записываем данные об авторе в s}

assign(f,'dddddd. txt'); {связываем файловую перем. с файлом}

rewrite(f); {открываем файл для записи}

writeln(f, s); {записываем имя автора из s в файл}

for i:=1 to 20 do {включаем цикл на 20 повторений}

begin

r:=random(10); {генерируем случайное число от 1 до 10}

STR(r, s); {преобразуем число r в строку s}

writeln(f, s); {записываем строку с числом в файл}

end;

close(f); {закрываем файл}

end.

ЗАДАЧА 2: Написать программу, читающую из текстового файла данные об авторе и 20-ть случайных цифр

var f:text;

r, i,c: integer;

s: string;

begin

assign(f,'dddddd. txt'); {связываем файловую перем. с файлом}

reset(f); {открываем файл для чтения}

readln(f, s); {читаем информацию об авторе в s}

writeln(s); {выводим информацию об авторе на экран}

for i:=1 to 20 do {включаем цикл на 20 повторений}

begin

readln(f, s); {читаем цифру из файла в строку s}

val(s, r,c); {переводим строку “s” в число “r”, в переменной “c” код возможной ошибки}

if c=0 then writeln(r); {если ошибки не было (с=0), то выводим цифру на экран}

end;

close(f); {закрываем файл}

end.

ЗАДАЧА 3: Вычислить корни квадратного уравнения и вывести результаты в файл.

Var a, b,c, x1,x2, d: real;

f:text;

Begin

Assign(f,’result. txt); {связываем файл с файловой переменной f)

Rewrite(f); {открываем файл для записи}

{Читаем исходные данные с клавиатуры и отправляем их в файл}

Readln(a, b,c);

Writeln(f, ‘решение квадратного ур-я’);

Writeln(f, 'a=',a:6:3,'b=', b:6:3,'c=',c:6:3);

{Расcчитываем корни квадратного уравнения}

D:=b*b-4*a*c;

If d>=0 then Begin X1:=-b+sqrt(d)/(2*a); X2:=-b-sqrt(d)/(2*a); End;

{Выводим результат в файл}

If d<0 then writeln(f,’у урав-я нет корней’)

else writeln(f, ‘корни: x1=’, x1:6:3,’x2=’, x2:6:3);

{Закрываем файл и заканчиваем работу программы}

Close(f);

Writeln(‘рез-ты работы программы в файле result. txt’);

Readln;

end.

На диске имеется файл с именем Karl. txt, в котором записана скороговорка: "Карл у Клары украл кораллы, Клара у Карла украла кларнет." Требуется подсчитать кол-во букв «К»

Var f:text; s:integer; a:char;

Begin

{Связываем файл с файловой переменной и открываем его для записи}

Assign(f,’Karl. txt’); Reset(f);

S:=0;

{последовательно просматриваем все строки файла до последней}

While not eof(f) do

Begin

{последовательно читаем все символы строки до последнего в строке и сверяем его с 'k'}

While not eoln(f) do

Begin Read(f, a); If a=’k’ then s:=s+1; End;

{переходим на следующую строку файла}

Readln(f);

End;

Close(f);

Writeln(s);

end.

Ввести текст в текстовый файл f1. Переписать строку из файла f1 в f2 – первую половину файла в прямом, а вторую – в обратном порядке следования символов.

Var f1,f2:text; s, snew, sa, sb: string; n, y,i: integer;

Begin

{Связываем файлы с файловыми переменными}

Assign(f1,’file1’); Assign(f2,’file2’);

{Читаем строку с клавиатуры и отправляем её в файл №1}

Rewrite(f1); Readln(s); Writeln(f1,s); Close(f1);

{Читаем строку из файла №1}

Reset(f1); Read(f1,s1); Close(f1);

{Находим середину строки}

N:=length (s1); Y:=n div 2;

{В новую переменную записываем первую половину строки в прямом, вторую половину в обратном порядке}

SNew:=’’;

For i:=1 to y do

Snew:=Snew+s1[i];

For i:=n downto y+1 do

Snew:=sew+s1[i];

{Записываем новую строку в файл №2}

Rewrite(f2); Writeln(sNew); Write(f2,sNew); Close(f2);

End.