Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Ситкин. Информатика. Программирование в DELPHI

.pdf
Скачиваний:
142
Добавлен:
18.07.2019
Размер:
1.49 Mб
Скачать

Классификация логических файлов

Логические файлы делятся на три вида: текстовые, типизован-

ные и нетипизованные в зависимости от способа обработки файла.

В любой момент времени программе доступен только один эле-

мент файла, на который ссылается указатель текущей позиции (указа-

тель чтения/записи). При открытии или создании файла указатель по-

мещается в его начало (нулевая позиция). Чтение/запись элемента данных файла приводит к автоматическому перемещению указателя в следующую позицию. Заканчивается файл спецсимволом eof.

Текстовый файл состоит из последовательности символов,

сгруппированных в строки. Каждая строка заканчивается спецсимво-

лом eoln. С текстовыми файлами можно работать только последова-

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

Типизованный файл состоит из последовательности элементов одного типа и имеет длину. Все элементы типизованного файла име-

ют одинаковую длину (под каждый выделено одинаковое число байт памяти), поэтому позиция каждого элемента легко вычисляется, и

указатель чтения/записи может быть перемещён на любой элемент файла. Это прямой доступ к файлу. Это файлы прямого доступа.

Нетипизованные файлы в основном используют для быстрого прямого доступа к любому файлу на диске, когда структура файла не-

известна или не имеет значения (например, при выполнении копиро-

вания). Любой текстовый или типизованный файл можно открыть и работать как с нетипизованным набором данных прямого доступа.

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

121

рая должна быть объявлена в разделе описаний:

для текстовых логических файлов

var имя_файловой_переменной : textfile;

для типизованных логических файлов

var имя_файловой_переменной : file of тип файла ;

для нетипизованных логических файлов var имя_файловой_переменной : file;.

Пример объявлений

var g: textfile; //текстовый файл

f: file of byte; //файл целых чисел (типизованный файл) f1, f2 file of real; //два файла вещественных чисел my_file: file; //нетипизованный файл

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

При обработке файла нужно: связать файл с файловой перемен-

ной, объявив её; открыть файл для чтения данных или записи данных

(или создать файл); обработать файл; закрыть файл. При этом исполь-

зуют стандартные процедуры и функции для работы с файлами.

AssignFile(f, 'Имя файла') связывает физический файл Имя файла с файловой переменной f . Если приложение находится в од-

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

(собственно само имя и расширение) без полного пути доступа.

Reset(f) открывает текстовый файл, связанный с файловой пе-

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

При повторном вызове переводит указатель чтения в начало файла.

122

Read(f, список ввода ) считывает данные из файла, связанно-

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

нии чисел из текстовых файлов сначала происходит автоматическое преобразование изображений чисел (тип string) в тип переменных списка ввода, который указывается при их объявлении в проекте. За-

тем эти числа записываются в переменные списка ввода с учётом раз-

делителя (пробел, конец строки).

Readln(f, список ввода ) то же, но после считывания данных перемещает указатель чтения в начало следующей строки (даже если из текущей строки считаны не все данные). Если список ввода отсут-

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

Rewrite(f) открывает файл, связанный с файловой переменной f , для перезаписи (удаляет предыдущую версию файла). Если файл не был создан, то создаёт его.

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

Write(f, список вывода ) записывает данные в файл, связан-

ный с файловой переменной f , с места текущего положения указателя записи, содержащиеся в константах или переменных списка вывода.

При выводе чисел в текстовый файл происходит автоматическое пре-

образование в их изображения.

Writeln(f, список вывода ) то же, но после записи данных пе-

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

Процедуры Readln и Writeln запрещены при работе с типизован-

ными файлами.

123

CloseFile(f) закрывает файл, связанный с файловой перемен-

ной f. Однако связь файла с f не теряется, он может быть повторно от-

крыт без повторного обращения к процедуре AssignFile.

Seek(f, n) переводит указатель чтения/записи с текущей пози-

ции в позицию n (целое число) типизованного файла, связанного с файловой переменной f, не производя при этом чтение или запись.

FileSize(f) функция, возвращающая целое число элементов в типизованном файле, связанным с файловой переменной f.

FilePos(f) функция, возвращающая текущую позицию указате-

ля чтения/записи (целое число) в типизованном файле, связанным с файловой переменной f.

Eoln(f) функция, возвращающая значение True, если текущая позиция указателя чтения/записи последняя в строке текстового фай-

ла, связанного с файловой переменной f , или False, если не последняя

Eof(f) функция, возвращающая значение True, если текущая позиция указателя чтения/записи последняя в файле, связанного с файловой переменной f , или False, если не последняя.

{$I } директива компилятору на отключение автоматической обработки ошибок ввода/вывода (доступа к файлу). Применяется, ко-

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

{$I+} директива компилятору на включение автоматической обработки ошибок ввода/вывода (доступа к файлу).

IOResult функция, возвращающая значение 0, если ошибок ввода/вывода нет, в противном случае возвращает код ошибки (не ра-

вен 0). Доступна при включённой обработке ошибок ({$I+}).

124

Пример 10.1

Считаем данные в виде последовательности символов из файла и запишем их в другой файл в обратной последовательности.

Создадим файл в текстовом редакторе «Блокнот» с именем

«File1.txt», запишем в него какие-либо символы в строку и сохраним в папку проекта. Второй файл (для вывода) можно не создавать.

Для хранения символов в памяти будем использовать динамиче-

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

Предусмотрим также программный контроль процесса открытия фай-

ла для чтения данных и наличия данных в нём, т.к. любая из этих ошибок приведёт к аварийной остановке работы приложения. procedure TForm1.Button1Click(Sender: TObject);

var f, g:file of char; //объявление двух типизованных файлов символов x:array of char; //объявление динамического символьного массива

i, n:byte;

begin

AssignFile(f, 'File1.txt'); //связывание физ. файла с файловой переменной

{$I } //отключение автоматической обработки ошибок ввода/вывода

Reset(f); //открытие 1-го файла для считывания данных

{$I+} //восстановление автоматической обработки ошибок ввода/вывода

if IOResult < >0 then //если есть ошибка доступа к файлу, то закрыть прил-е begin showmessage('Файл не найден. Приложение закрыть'); Halt; end; n:=FileSize(f); //определение количества символов в первом файле

if n=0 then //если данных в файле нет, то закрыть файл и приложение

begin ShowMessage('Файл пуст. Прил-е закрыть'); CloseFile(f); Halt; end;

AssignFile(g, 'File2.txt'); //связывание физ. файла с файловой переменной

Rewrite(g); //открытие (создание) 2-го файла для перезаписи (записи) данных

125

SetLength(x,n); //выделение памяти под массив ровно сколько символов

for i:=0 to n 1 do Read(f, x[i]); //посимвольное считывание в массив

for i:=n 1 downto 0 do Write(g, x[i]); //посимвольная запись во 2-ой файл

SetLength(x,0); //высвобождение памяти из-под массива

CloseFile(f); CloseFile(g); //закрытие обоих файлов

end;

Программная проверка открытия второго файла не предусмот-

рена, т.к. если файла для записи данных нет, то процедура Rewrite со-

здаст его. А если бы он открывался процедурой Reset (она позволяет не только читать, но и записывать в типизованные файлы), то провер-

ку следовало бы предусмотреть, т.к. она только открывает файл.

Отметим, что разработанное приложение жёстко связано с про-

писанными в проекте внешними файлами (их адресами). Это исклю-

чает возможность выбора пользователем файла, с которого считыва-

ются исходные данные и файла записи результатов.

Компоненты OpenDialog

и SaveDialog

вкладка dialogs

Предназначены для загрузки стандартных окон Windows откры-

тия и сохранения файла соответственно, и предоставляют возможно-

сти по настройке свойств окон на этапе конструирования. Из этих окон пользователь во время работы приложения может выбирать файлы для считывания или записи данных. Это обстоятельство делает работу приложения более гибкой. Оба компонента невизуальные во время работы приложения на форме не видны. Их значки видимы только на этапе разработки формы. Пиктограммы компонентов рас-

положены на вкладке Dialogs палитры компонентов. Свойства обоих компонентов сходны, основные из них представлены в табл. 10.1.

126

Таблица 10.1 Основные свойства компонентов OpenDialog и SaveDialog

Свойство

 

Описание

(метод)

 

 

 

Name

Имя компонента. Используется для доступа к

компоненту и его свойствам

 

 

Вызов окна открытия или сохранения файла.

Execute

Имеет значение True, если пользователь выбрал

файл в окне и щёлкнул «Открыть» («Сохранить»)

(метод)

и значение False, если файл не был выбран или

 

 

пользователь щёлкнул «Отмена» или закрыл окно

Title

Заголовок окна. Если свойство пустое, то в заго-

ловке записано «Открыть» («Сохранить как»)

 

 

Устанавливает папку, которая будет открыта в

InitialDir

момент загрузки окна открытия или сохранения

файла. Если свойство пустое, то будет открыта

 

 

папка, открытая при последней загрузки окна

 

Позволяет настроить: имена файлов какого типа

Filter

будут отображены в окне по выбранному имени

фильтра

Filter Name. Если свойство пустое, то

 

 

отображаются имена всех файлов

FileName

Получает значение строкового типа равное имени

выбранного файла с полным путём доступа

 

Для выбора типа отображаемых файлов в окне диалога на этапе

конструирования формы нужно щёлкнуть кнопку открытия редактора фильтров в свойстве Filter в окне Object Inspector для компонента

OpenDialog или SaveDialog (рис. 10.1). В открывшемся окне Filter Editor

 

имя фильтра

 

 

 

 

 

 

 

 

 

 

 

 

 

 

кнопка запуска

 

расширения файлов,

редактора фильтров

 

отображаемых в окне

Рис. 10.1

127

слева программист прописывает имена фильтров, а справа, через точ-

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

Пример 10.2

Разработаем проект для считывания чисел прямоугольной мат-

рицы из внешнего файла в соответствующий двумерный массив.

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

ло строк и столбцов матрицы. Так как это можно будет сделать толь-

ко по ходу работы программы, массив объявим динамическим, а па-

мять под него выделим после определения размера матрицы.

Для реализации возможности выбора файла пользователем, с

которого будут считываться данные, обеспечим загрузку окна открытия файла, разместив на форме компонент OpenDialog. Установим воз-

можность выбора только текстовых файлов, создав фильтр (рис. 10.1).

Если файл не будет выбран пользователем или будет выбран, но ока-

жется недоступным (ошибка открытия), предусмотрим досрочное за-

вершение работы с выдачей соответствующего сообщения (рис. 10.2).

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

зователя об отсутствии данных и также досрочно завершим работу.

После тройной проверки, в случае успешного её прохождения,

переходим непосредственно к обработке содержимого файла.

128

начало

файл нет

выбран

да

открыть

файл

ошибка да открытия

нет

конец да

файла

нет

счётчик строк

m=0, столбцов n = 0

перевод

строки

m = m + 1

нет конец

файла

да

переоткрыть

файл

перевод

поз. чтения в строке

n = n + 1

нет конец

строки

да

переоткрыть

файл

1

файл не выбран

файл не найден

файл

закрыть

пустой

файл

 

 

1

выделить память m n

номер строки

 

 

 

i = 0

 

 

 

 

 

 

 

 

 

 

i m 1

нет

закрыть

 

 

файл

 

 

 

да

 

 

 

 

 

 

номер столб-

 

 

 

ца j = 0

 

 

 

 

 

нет

j n 1

 

 

 

 

да

 

 

 

ввод xij

 

 

i = i + 1

из файла

 

 

 

 

 

ошибка

 

 

 

да

2

ввода xij

нет

 

 

 

j = j + 1

2

ошибка

синтаксиса

закрыть

файл

высвободить память m n

конец

Рис. 10.2

129

Переводя в цикле указатель чтения по строкам и считая количе-

ство раз перевода строки, пока не достигнем конца файла, определим число m этих строк. Чтобы вернуть указатель чтения в начало первой строки (в начало файла), повторно откроем файл. Во втором цикле,

переводя указатель чтения по элементам первой строки, пока не будет достигнут её конец, аналогично определим число n столбцов. Зная те-

перь размеры матрицы, выделим память под массив размером m n.

Вновь вернув указатель чтения в начало файла (к первому элементу матрицы), начнём считывание элементов из файла по одному, после-

довательно продвигаясь по строкам и столбцам. Для этого применим знакомую конструкцию вложенных циклов. Предусмотрим про-

граммный контроль ввода текущего элемента в память, отключив ав-

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

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

ственное число), закроем файл, завершив его обработку досрочно. Ес-

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

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

чи ввод элементов из файла. Поэтому, в случае успешного ввода всех элементов, память из-под массива не высвобождается, сам мас-

сив следует объявить глобальным для возможности его использова-

ния в другой процедуре или дополнить данную обработкой массива.

130