В любой момент времени программе доступен только один элемент файла, на который ссылается текущий указатель (указатель обработки).
Как правило, все действия с файлом (чтение из файла, запись в файл) производятся поэлементно, причем в этих действиях участвует тот элемент файла, который обозначается текущим указателем. В результате совершения операций текущий указатель может перемещаться, настраиваясь на тот или иной элемент файла.
По способу доступа к элементам различают файлы последовательного и прямого доступа.
Файлом последовательного доступа называется файл, к элементам которого обеспечивается доступ в такой же последовательности, в какой они записывались.
Файлом прямого доступа называется файл, доступ к элементам которого осуществляется по адресу элемента. Например, для поиска нужного элемента в последовательном файле необходимо, начиная с нулевого, перемещать указатель обработки до тех пор, пока он не будет указывать на искомый элемент, а при поиске нужного элемента в файле прямого доступа достаточно указать номер его позиции. При организации данных в файл последовательного доступа нельзя одновременно читать данные из файла и записывать данные в файл, так как для чтения некоторого элемента последовательного файла указатель обработки помещен на данный элемент, а для записи нового элемента этот указатель одновременно должен быть в конце файла.
Компилятор Турбо Паскаля поддерживает три типа файлов: текстовые, типизированные, нетипизированные.
Средства обработки файлов.
TURBO PASCAL вводит ряд процедур и функций, применимых для любых типов файлов: Assign, Reset, Rewrite, Close, Rename, Erase, Eof, IOResult.
Файловая система на Паскале наиболее полно использует возможности операционной системы по передаче данных. Каждому файлу в языке ставится в соответствие файловая переменная определенного типа, поэтому перед началом работы с файлом необходимо установить данное соответствие. Для этого в языке используется процедура:
Процедура Assign( var f; FileName: String ) связывает логический файл f с физическим файлом, полное имя которого задано в строке FileName.
Процедура Assign всегда предшествует другим процедурам работы с файлами, так как ставит в соответствие конкретному файлу на внешнем устройстве логическую файловую переменную языка, к которой впоследствии будут обращаться все другие файловые процедуры. Недопустимо использование процедуры Assign для уже открытого файла.
При назначении файловой переменной пустой строки происходит автоматическая ссылка на стандартный файл ввода, что в модуле SYSTEM соответствует устройству CON. С открытием такого файла появляется возможность ввода данных с клавиатуры.
Процедура Reset ( var f ) открывает логический файл f для последующего чтения данных или, как говорят, открывает входной файл. После успешного выполнения процедуры Reset файл готов к чтению из него первого элемента.
Имеются некоторые отличия в использовании процедуры Reset при открытии различных типов файлов. В отношении текстовых файлов (тип Text) действие процедуры означает открытие файла только для чтения. Дня нетипизированных файлов в описание процедуры добавляется еще один параметр RecSize типа word, который устанавливает длину записи для функций обмена с файлом.
Процедура Rewrite( var f ) открывает логический файл f для последующей записи данных (открывает выходной файл). После успешного выполнения этой процедуры файл готов к записи в него первого элемента.
Процедура Rewrite создает и открывает новый файл. Использование этой процедуры требует особого внимания. При попытке создать и открыть новый файл с именем уже существующего на диске набора данных действие процедуры Rewrite сведется к удалению этого набора и созданию нового пустого файла с тем же именем.
При открытии новых нетипизированных файлов для задания длины записи в описание процедуры Rewrite добавляется дополнительный параметр RecSize типа word.
Если процедура Rewrite используется для текстового файла, то к открываемому новому набору данных в дальнейшем могут быть применимы только операции записи.
Процедура Close( var f ) закрывает открытый до этого логический файл.
Вызов процедуры Close необходим при завершении работы с файлом. Если по какой-то причине процедура Close не будет выполнена, файл все - же будет создан на внешнем устройстве, но содержимое последнего буфера в него не будет перенесено. Для входных файлов использование оператора закрытия файла необязательно. Использование процедуры Close позволяет устранить связь файловой переменной с внешним файлом, установленную с помощью процедуры Assign.
Логическая функция EOF( var f ): Boolean возвращает значение TRUE, когда при чтении достигнут конец файла. Это означает, что уже прочитан последний элемент в файле или файл после открытия оказался пуст.
Процедура Rename( var f; NewName: String ) позволяет переименовать физический файл на диске, связанный с логическим файлом f. Переименование возможно после закрытия файла.
Процедура Erase( var f ) уничтожает физический файл на диске, который был связан с файловой переменной f. Файл к моменту вызова процедуры Erase должен быть закрыт.
Обе процедуры нельзя использовать для уже открытых файлов. В противном случае могут возникнуть нежелательные последствия со стороны операционной системы. Единственным стандартным шагом перед использованием процедур является установка связи между внешним файлом с конкретным именем и файловой переменной. Операции удаления и переименования осуществляются только для реально существующих файлов, иначе возникает ошибка выполнения программы.
При обращении к стандартным функциям и процедурам ввода/вывода автоматически производится проверка на наличие ошибок. При обнаружении ошибки программа прекращает работу и выводит на экран сообщение. Иногда это не удобно. С помощью директив компилятора {$I+} и {$I-} автоматическую проверку ошибок ввода/вывода можно включить или выключить. Если автоматическая проверка отключена, ошибки ввода/вывода, возникающие при работе программы, не приводят к ее останову. Стандартная функция IOResult возвращает код ошибки. Использование этой функции в программах возможно лишь в том случае, если на время выполнения файловых операций отключена стандартная проверка операций ввода-вывода. Нулевое значение кода ошибки означает нормальное завершение операции ввода/вывода.
Рассмотренные операции ввода-вывода охватывают все типы файлов в Турбо Паскале и характеризуют взаимоотношения файловой и операционной систем.
Текстовые файлы
Текстовый файл содержит последовательность символов, организованных в строки, причем каждая строка заканчивается специальным символом возврата каретки CR=#13 и перевода строки LF=#10. Эти два символа задают стандартные действия по управлению текстовыми файлами. Стандартно открываемые предопределении файлы Input и Output в модуле System имеют тип Text. Заканчивается файл признаком конца файла.
Для текстовых файлов в Паскале имеется стандартный файловый тип text. Прежде чем приступить к операциям над текстовыми файлами, необходимо описать переменные типа text:
var f: Text; {F — файловая переменная}
Далее переменная f сопоставляется внешнему файлу на диске или какому-нибудь устройству процедурой Assign:
Assign(in_file, ‘primer.txt’);
Assign(in_file, ‘C:\text\primer.txt’);
Assign(in_file, ‘prn’);
После установления связи внешнего файла с файловой переменной внешний фал надо открыть для записи или чтения. Текстовый файл можно открыть процедурой Reset(my_file) только для чтения, процедурой Rewrite(my_file) – только для записи, и процедурой Append(my_file) – для добавления информации.
Procedure Reset(var F) | Открывает существующий файл, связанный с файловой переменной F. При отсутствии файла, выдается сообщение об ошибке. Текущий указатель устанавливается в начало файла. Текстовый файл открывается только для чтения |
Procedure Rewrite(var F) | Создает и открывает новый файл, связанный с файловой переменной F. Если файл с указанным именем уже существует, старый файл будет стерт, а на его месте создан новый пустой файл. Текущий указатель устанавливается в начало файла |
Procedure Append(var F: text) | Открывает существующий файл, связанный с файловой переменной F, для добавления в него новых записей |
Доступ к текстовому файлу организуется последовательно, то есть программа не может в любой момент времени считать из него произвольную порцию информации или произвести запись в произвольное место файла. Файл представляет собой линейную последовательность элементов, каждый из которых имеет свой номер. Указатель при считывании очередного элемента файла перемещается к следующему элементу.
Для записи в текстовый файл или чтения из него можно использовать процедуры Write, WriteLn, Read, ReadLn. В этом случае в качестве первого параметра в этих процедурах указывается файловая переменная, например: Read(f, a, x).
У текстовых файлов своя специфика. Специальные расширения стандартных процедур чтения Read и записи Write разрешают работать со значениями несимвольного типа. При считывании значений или их записи в файл происходит автоматическое преобразование из числового формата в символьный и наоборот.
Другими словами, последовательность символов автоматически преобразуется к значению того типа переменной, которая используется в файловых операциях.
Procedure Read(var F:Text, v1,…) | Считывает одно или несколько значений из файла, связанного с файловой переменной F, в одну или несколько переменных v1,… |
Procedure ReadLn(var F:Text, v1,…) | То же, что и Read, но выполняет после считывания пропуск до начала следующий строки текстового файла |
ReadLn(F) | пропускает строку до начала следующей; |
Procedure Write(var F:Text, v1,…) | Записывает в файл, связанный с файловой переменной F, одно или несколько значений, хранящихся в переменных v1,… Значения могут иметь целый, вещественный, строковый, символьный или булевский тип |
Procedure WriteLn(var F:Text, v1,…) | То же, что и Write, но затем записывает в текстовый файл признак конца строки |
WriteLn(F) - | Завершает строку файла, в которую производится запись, признаком конца строки и переходит к началу следующей. |
Вспомогательные процедуры и функции для работы с текстовыми файлами:
Function SeekEOF(var F: text): Boolean | возвращает значение True, если до конца файла остались строки, заполненные пробелами. |
Function SeekEOLn(var F: text): Boolean | возвращает значение True, если до конца строки остались только пробелы. |
Функция Eoln(var F: text) | возвращает булевское значение True, если текущая файловая позиция находится на маркере конца строки |
Типизированные файлы
Типизированные файлы используются для хранения однородной (по типу) информации. Если речь идет о хранении числовых данных, следует использовать типизированные файлы.
Типизированные файлы состоят из машинных представлений значений переменных, они хранят данные в том же виде, что и память ЭВМ.
Описание типизированного файла имеет вид:
var ftable: file of type_ID;
где Type_ID может быть любым типом за исключением файлового. Элементами типизированного файла являются значения указанного типа.
При работе с типизированными файлами используются уже знакомые процедуры Assign, Reset и ReWrite. Однако следует заметить, что текстовый файл, открытый процедурой Reset, доступен только для чтения, а типизированный – еще и для записи. Процедуры Read и Write здесь используются по-другому. Отличие заключается в том, что каждый из параметров в рассматриваемом случае должен быть переменной типа type_ID, а выражения и константы недопустимы. Процедуры ReadLn и WriteLn к типизированным файлам не применяются.
Типизированные файлы являются файлами с прямым доступом, т.е. в любой момент можно считать любой элемент из файла по его номеру и записать элемент на необходимое место в файл.
К типизированным файлам применяются следующие процедуры и функции:
Function EOF(var F): Boolean | Возвращает для файла, связанного с файловой переменной F, состояние End-Of-File (конец файла); True – если текущее положение указателя находится в конце файла или файл пустой; False – во всех остальных случаях |
Function FilePos(var F): LongInt | Возвращает текущую позицию для файла, связанного с файловой переменной F. При положении текущего указателя в начале файла возвращается нулевое значение |
Function FileSize(var F): LongInt | Возвращает текущий размер файла, связанного с файловой переменной F. Если файл пустой, возвращается нулевое значение |
Procedure Seek (var F: N: LongInt) | Перемещает текущую позицию в файле, связанным с файловой переменной F, на заданный элемент. Началу файла соответствует нулевое значение N |
Процедура Truncate( var f ) | Устанавливает в текущей позиции признак конца файла и удаляет (стирает) все последующие блоки. |
Нетипизированные файлы
Для более эффективного выполнения операций ввода/вывода из внешних файлов в Паскале имеются нетипизированные файлы. При работе с ними можно использовать быстрые дисковые операции низкого уровня. Нетипизированные файлы дают возможность прямого доступа к любому файлу независимо от его типа и структуры. Описание нетипизированной файловой переменной имеет вид
var untypfile: file;
Такая файловая переменная связывается с внешним файлом обычным образом. В числе параметров процедур Reset и Rewrite для нетипизированных файлов кроме файловой переменной имеется необязательный второй параметр типа Word:
Reset(untypfile, n);
Rewrite(untypfile, n);
Дополнительный параметр n описывает размер индивидуальной записи в файле (в байтах). Если параметр n отсутствует, его значение по умолчанию принимается равным 128, однако рекомендуется явно указывать значение 1.
Для операций ввода/вывода в нетипизированных файлах используются следующие низкоуровневые операции:
Procedure BlockRead (var F: File; var Buf; Count:Word) | Считывает из нетипизированного файла, связанного с файловой переменной F, одну или несколько записей (их количество задается целочисленным выражением Count) в переменную Buf |
Procedure BlockWrite (var F: File; var Buf; Count:Word) | Записывает в нетипизированный файл, связанный с файловой переменной F, одну или несколько записей (их количество задается целочисленным выражением Count) из переменной Buf |