4 Файловые типы данных в языке программирования Паскаль.
Под файлом понимается либо именованная область внешней памяти ПК (жесткого диска, гибкой дискеты, электронного «виртуального» диска), либо логическое устройство — потенциальный источник или приемник информации.
Любой файл имеет три характерные особенности. Во-первых, у него есть имя, что дает возможность программе работать одновременно с несколькими файлами. Во-вторых, он содержит компоненты одного типа. Типом компонентов может быть любой тип Турбо Паскаля, кроме файлов. Иными словами, нельзя создать «файл файлов». В-третьих, длина вновь создаваемого файла никак не оговаривается при его объявлении и ограничивается только емкостью устройств внешней памяти.
Синтаксическая диаграмма для файловых типов выглядит так:
Файловый тип или переменную файлового типа можно задать одним из трех способов:
Здесь — имя файлового типа (правильный идентификатор);
FILE, OF — зарезервированные слова (файл, из);
TEXT — имя стандартного типа текстовых файлов;
— любой тип Турбо Паскаля, кроме файлов.
text80 = file of String [80] ;
В зависимости от способа объявления можно выделить три вида файлов:
типизированные файлы (задаются предложением FILE OF. );
текстовые файлы (определяются типом TEXT);
нетипизированные файлы (определяются типом FILE).
В наших примерах F1, F4 и F5- типизированные файлы, F2 — текстовый файл, F3 -нетипизированный файл. Вид файла, вообще говоря, определяет способ хранения информации в файле. Однако в Турбо Паскале нет средств контроля вида ранее созданных файлов. При объявлении уже существующих файлов программист должен сам следить за соответствием вида объявления характеру файла.
Любой программе доступны два предварительно объявленных файла со стандартными файловыми переменными: INPUT — для чтения данных с клавиатуры и OUTPUT — для вывода на экран. Стандартный Паскаль требует обязательного упоминания этих файлов в заголовке программы, например, так:
В Турбо Паскале это необязательно, вот почему заголовок программы можно опускать.
Любые другие файлы, а также логические устройства становятся доступны программе только после выполнения особой процедуры открытия файла (логического устройства). Эта процедура заключается в связывании ранее объявленной файловой переменной с именем существующего или вновь создаваемого файла, а также в указании направления обмена информацией: чтение из файла или запись в него.
Файловая переменная связывается с именем файла в результате обращения к стандартной процедуре ASSIGN(, ), если имя файла задается в виде пустой строки, например, ASSIGN(f, ‘ ‘), то в зависимости от направления обмена данными файловая переменная связывается со стандартным файлом INPUT или OUTPUT.
Инициировать файл означает указать для этого файла направление передачи данных. В Pascal можно открыть файл для чтения, для записи информации, а также для чтения и записи одновременно.
Для чтения файл инициируется с помощью стандартной процедуры Reset () — при выполнении этой процедуры дисковый файл подготавливается к чтению информации. В результате специальная переменная-указатель, связанная с этим файлом, будет указывать на начало файла, т. е. на компонент с порядковым номером 0.
Для текстовых файлов, открытых процедурой Reset, нельзя использовать процедуру Write или WriteLn.
Стандартная процедура Rewrite () — инициирует запись информации в файл, связанный с файловой переменной . Процедурой Rewrite нельзя инициировать запись информации в ранее существовавший дисковый файл: при выполнении этой процедуры старый файл (если он был) уничтожается и никаких сообщений об этом в программу не передается. Новый файл подготавливается к приему информации, и его указатель принимает значение 0.
Стандартная процедура Append () — инициирует запись в ранее существовавший текстовый файл для его расширения, при этом указатель файла устанавливается в его конец. Процедура Append применима только к текстовым файлам, т. е. их файловая переменная должна иметь тип TextFile (см. выше). Процедурой Append нельзя инициировать запись в типизированный или нетипизированный файл. Если текстовый файл ранее уже был открыт с помощью Reset или Rewrite, использование процедуры Арpend приведет к закрытию этого файла и открытию его вновь, но уже для добавления записей.
Процедура CLOSE () — закрывает файл, однако связь файловой переменной с именем файла, установленная ранее процедурой ASSIGN, сохраняется.
Функция EOF () : BOOLEAN — логическая функция, тестирующая конец файла. Возвращает TRUE, если файловый указатель стоит в конце файла. При записи это означает, что очередной компонент будет добавлен в конец файла, при чтении -что файл исчерпан.
Файлы
Наверняка вы уже задавались вопросом, как сохранить какие-то данные программы на диске, а потом прочитать их. Очень часто в файлах хранятся разные настройки программы. На первых этапах файлы также можно использовать для обмена данными между программами.
Вообще работа с файлами — это огромная тема. Этому можно посвятить отдельную книгу. Но новичкам слишком много информации знать не нужно, так как ничего кроме путаницы в голове это не вызовет. Поэтому здесь мы ограничимся лишь краткими сведениями о работе с файлами на примере языка Паскаль.
Итак, начнём с того, что понятие файл в Паскале имеет дав смысла:
- Это информация на внешнем устройстве (то есть обычный файл на диске) — внешний файл.
- И это переменная файлового типа — внутренний файл.
Чтобы начать работать с внешним файлом, нужно установить связь между внутренним и внешним файлом. И тогда, всё что будет происходить с внутренним файлом, будет также происходить и с внешним файлом.
Говоря по простому, для того, чтобы начать работать с файлом в вашей программе, нужно
связать с внешним файлом файловую переменную
Делается это так. Сначала объявляем файловую переменную:
Теперь с этой переменной можно работать. Например, так:
Assign(iFile, 'ifile.txt'); //Связать переменную с файлом Rewrite(iFile); //Открыть файл для записи Write(iFile, 100); //Записать в файл число 100 Close(iFile); //Закрыть файл
Здесь мы связываем объявленную ранее файловую переменную iFile с реальным файлом на диске. Этого файла на диске может и не быть, но имя файла должно быть правильным именем файла, допустимым в операционной системе, для которой создаётся программа.
Далее мы открываем файл для записи, а затем записываем в него число 100.
После завершения работы с файлом его нужно обязательно закрыть. Иначе могут возникнуть утечки памяти и другие проблемы.
Функция Rewrite не только открывает файл для записи, но и создаёт его, если этого файла раньше не было. Если файл был, то он будет перезаписан. Поэтому будьте внимательны. По идее, надо сначала проверить существование файла, и только потом принимать решения, что делать дальше.
В нашем примере мы создаём файл с именем iFile.txt в той же папке, откуда была запущена программа. Если нужно создать файл в другом месте, то нужно указывать полный путь к файлу. Если вы не знаете, что такое полный путь к файлу, то рекомендую прочитать книгу Компьютер для чайника.
После этих манипуляций появится новый файл с указанным именем и там будет записано число 100. Вы можете открыть этот файл и посмотреть. Возможно, вас удивит, что в файле будет записана одна буква d. Но всё объясняется просто. Обычный текстовый редактор не может работать с двоичными данными. Поэтому он воспринимает число 100 как букву (100 — это ASCII-код латинской буквы d).
Если вы откроете этот файл с помощью шестнадцатеричного редактора, то вы увидите число 64, а не 100. И здесь тоже всё просто — шестнадцатеричный редактор отображает числа в шестнадцатеричном формате. А 64 в шестнадцатеричной системе — это 100 в десятичной системе.
Итак, мы умеем создавать файлы и записывать в них информацию. Теперь научимся читать файл.
Assign(iFile, 'ifile.txt'); //Связать переменную с файлом Reset(iFile); //Открыть файл для чтения Read(iFile, i); //Прочитать данные из файла в i Close(iFile); //Закрыть файл
Открываем файл с помощью функции Reset. Читаем данные из файла с помощью функции Read и сохраняем их в переменной i.
ВАЖНО!
Файл должен существовать по указанному пути, иначе возникнет ошибка времени выполнения программы.
Записывать в файл всего одно число конечно можно. А иногда этого вполне достаточно. Однако может возникнуть необходимость записать несколько однотипных чисел. Сделать это можно так:
Assign(iFile, 'ifiles.txt'); //Связать переменную с файлом Rewrite(iFile); //Открыть файл для записи for i := 0 to 15 do //Записать в файл 16 чисел Write(iFile, i); //от 0 до 15 Close(iFile); //Закрыть файл
Прочитать такой файл можно так:
Reset(iFile); //Открыть файл для чтения for i := 0 to 15 do //Прочитать из файла begin Read(iFile, j); //первые 16 чисел Write(j, ' '); //и вывести на экран end; Close(iFile); //Закрыть файл
ВАЖНО!
Если при чтении файла с несколькими значениями вы попытаетесь прочитать больше чисел, чем записано в файле, то это приведёт к ошибке во время выполнения программы. Поэтому читать файлы таким образом можно только тогда, когда вы точно знаете, сколько значений хранится в файле.
Но как быть, если вам не нужно читать все значения? Как получить доступ к конкретному значению в файле?
Есть специальная функция, которая может переместить указатель файла в любое его место.
Reset(iFile); //Открыть файл для чтения Seek(iFile, 8); //Переместить указатель на 8-ю позицию Read(iFile, j); //Прочитать число 8-й позиции Write(j); //Вывести на экран Close(iFile); //Закрыть файл
Функция Seek перемещает указать на заданную позицию. Обратите внимание, что в нашем примере мы начинаем отсчёт с нуля, поэтому 8-я позиция содержит число 8, хотя фактически это 9-е число в файле.
Тип файловой переменной может быть любым, кроме файлового. В том числе пользовательским. Это означает, что вы можете хранить в файле сложные структуры данных, такие как записи, массивы и т.п.
Это, в свою очередь, означает, что вы таким образом можете сохранять в файлах (а затем читать), например, какие-то настройки программы.
Файловые переменные могут быть типизированными или нетипизированными. Типизированная файловая переменная — это файл с данными какого-то типа. Нетипизированная файловая переменная — это просто текстовый файл, который содержит какие-то произвольные данные. С таким файлом надо работать немного по другому.
Объявляется нетипизированная файловая переменная, например, так:
Записать данные в файл можно так:
Assign(nFile, 'nfile.txt'); //Связать переменную с файлом Rewrite(nFile); //Открыть файл для записи for i := 1 to 8 do //Записать в файл 8 строк WriteLn(nFile, i); Close(nFile);
Обратите внимание, что здесь мы используем функцию WriteLn, для того, чтобы записывать каждое число с новой строки. Разумеется, можно использовать и Write, но тогда всё будет записано в одну строку, а в некоторых случаях это неудобно.
Теперь прочитаем все строки файла и выведем их на экран.
Reset(nFile); //Открыть файл для чтения while not Eof(nFile) do //Пока не закончится файл begin ReadLn(nFile, str); //Читать строку WriteLn(str); //и выводить на экран end;
Перед тем, как использовать этот пример, надо объявить переменную str строкового типа.
Затем открываем файл для чтения, читаем каждую его строку и выводим на экран.
Поскольку мы можем не знать, сколько строк имеется в файле, то мы используем функцию Eof, которая возвращает TRUE, когда достигнут конец файла.
Есть ещё один момент, который может оказаться вам полезным. Если вам не нужно полностью перезаписывать файл, а достаточно добавить только одну строку, то можно использовать функцию Append, которая открывает файл для добавления данных. При этом все старые данные сохраняются, а новые данные добавляются в конец файла. Пример:
Append(nFile); //Открыть файл для добавления WriteLn(nFile, '100'); //Добавить новую строку Close(nFile); //Закрыть файл
ВАЖНО!
Обратите внимание, что функция Append сама открывает файл, то есть перед её использованием файл должен быть закрыт.
Ну что же, на этом остановимся, дабы не перегружать начинающих избыточной информацией. Для многих случаев этих знаний о работе с файлами вам будет вполне достаточно. Во всяком случае на начальном этапе обучения программированию.