На этом шаге мы рассмотрим работу с текстовыми файлами.
Для описания текстовых файлов используется предопределенный тип Text.
Ввод из текстовых файлов в языке Object Pascal осуществляется процедурами модуля System:
Read (<имя файловой переменной>, <список переменных>); и Readln (<имя файловой переменной>, <список переменных>); ,
а вывод в текстовый файл - процедурами:
Write (<имя файловой переменной>, <список элементов вывода>); Writeln (<имя файловой переменной>, <список элементов вывода>); .
Стандартный ввод выполняется из предопределенного текстового файла с именем Input, который связан с клавиатурой, а стандартный вывод выполняется в предопределенный текстовый файл с именем Output, который связан с монитором. В случае стандартного ввода-вывода имя файловой переменной в процедурах Read, Readln, Write, Writeln указывать не обязательно, так как по умолчанию для ввода принимается Input, а для вывода - имя Output. Таким образом, фрагменты:
Readln (Input,A, B); Writeln (Output, 'A=',A,' B=',B) ; и Readln (A,B); Writeln ('A=',A,' B=',B) ;
Во всех реализациях и версиях языка Pascal используется концепция так называемого поэлементного ввода-вывода. То есть значения переменных структурированных типов не могут быть введены (или выведены) одной процедурой ввода (вывода). Для ввода (вывода) таких переменных необходимо использовать операторы цикла. Исключение составляют переменные строковых типов.
При организации ввода-вывода из текстовых файлов необходимо также помнить, что:
Ввод значений вышеуказанных типов процедурами Read и Readln выполняется с учетом следующих правил.
1. Ввод значения в переменную символьного типа.
Программа:
var А,В,C : Char; begin Read (A); { А будет равно $. } Read (B); { В будет равно пробелу. } Read (C); { С будет равно 7. } end.
Исходный файл:
$ 7
Процедура Read считывает из файла один символ и присваивает егo переменной. Если перед выполнением процедуры Read функция Eof (конец файла) принимала значение True, то переменной присваивается символ с ASCII-кодом 26. Если функция Eoln (конец строки) имела значение True, то соответствующей переменной присваивается символ с ASCII-кодом 13 (символ возврата каретки). Следующая операция Read начнется со следующего символа в файле.
2. Ввод значения в переменную целого или вещественного типа.
Программа:
var А,В : Integer, X,Y : Real; begin Read (A) ; { А будет равно 77. } Readln (В); { В будет равно -34.24. } Read (X) ; { X будет равно 5.87е-5. } Readln (Y); { Y будет равно 555. } end.
Исходный файл:
77 -34.24 5.87е-5 555
Процедура Read ожидает поступления последовательности символов, образующих целое или вещественное число со знаком. Любые пробелы, знаки табуляции или признаки конца строки, предшествующие числовой строке, пропускаются. Выделение числа выполняется до обнаружения первого пробела, символа табуляции, признака конца строки или признака конца файла. Если выделенная последовательность символов не соответствует числовым форматам, то происходит ошибка ввода-вывода. Выполнение следующей процедуры Read начнется с пробела, символа табуляции или метки конца строки, на котором остановилось чтение предыдущим оператором.
3. Ввод значения в переменную строкового типа или в массив символов с нулевой базой (array [0..N] of Char).
{$X+} var A: array [0..5] of Char; S1,S2,S3 : String [10] ; begin Read (A); { А будет равно 'ААААА'. } Read (S1) ; { S1 будет равно 'ВВВВВВВ'. } Read (S2) ; { S2 будет равно пустой строке. } Readln; { Переход на новую строку. } Read (S3) ; {S3 будет равно 'ABCDEFGHIJ'.} end.
Исходный файл:
АААААВВВВВВВ ABCDEFGHIJ
Процедура Read считывает столько символов исходных данный сколько указано в объявлении строковой переменной. Пробел при этом разделителем, как при чтении в числовые переменные, не считается. Если в текущей строке исходных данных осталось символов меньше, чем требуется по описанию переменной, то будут прочитаны только наличные в этой строке символы. Выполнение следующей процедуры Read начинается с метки конца строки, которой завершилась предыдущая строка. То есть процедура Read при чтении строковой переменной переход на новую строку не делает. Такой переход может быть выполнен только про процедурой Readln.
Использование процедур Read и Readln для ввода значений в символьные массивы с нулевой базой допускается только при включенном расширенном синтаксисе (директива {$Х+}). Завершающий нуль-символ NULL (код ASCII 0) добавляется автоматически.
Отличие работы процедуры Readln от процедуры Read состоит том, что она после выполнения действий процедуры Read осуществляет переход на следующую строку исходных данных и в том, что вызов Readln без параметров приводит к перемещению текущей позиции чтения исходных данных в начало следующей строки, независимо от наличия/отсутствия данных в текущей строке.
Каждый элемент вывода процедур Write и Writeln имеет вид:
Ехрг [ : MinField [ : DecDigits ]]
DecDigits может указываться только в том случае, если Ехрг имеет вещественный тип и указан параметр MinField. Если DecDigits указывается, то число выводится в формате с фиксированной точкой, а если не указывается - то в формате с плавающей точкой.
Формат вывода с фиксированной точкой:
[<пробелы>] [-] <цифры> [.<зкаки дроб.части>]
Формат вывода с плавающей точкой:
[-] <цифра>.<знаки_дроб.части> Е [+|- <показатель_степени>]
Процедура Writeln является расширением процедуры Write для текстовых файлов, которая после выполнения действий процедуры Write записывает признак конца строки (символы "возврат каретки" и "перевод строки"). При вызове Writeln без параметров, в файл записывается только признак конца строки.
В приведенном ниже примере демонстрируется запись в текстовый файл значений различных типов.
unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls; type TForm1 = class(TForm) Label1: TLabel; Memo1: TMemo; procedure FormCreate(Sender: TObject); private { Private declarations } public { Public declarations } end; var Form1: TForm1; implementation {$R *.dfm} procedure TForm1.FormCreate(Sender: TObject); const i : Integer = 12345; r : Real = -123.1234567; c : Char = '$'; b : Boolean = True; s : String = 'Object Pascal'; var F : System.Text; begin { Запись данных в текстовый файл различными способами. } AssignFile(F,'WritDemo.Dat'); Rewrite(F); Writeln(F,'Печать без форматирования'); Writeln(F,i,r,c,b,s); Writeln(F); Writeln(F,'Форматированная печать'); Writeln(F,i:10,r:10:3,c:10,b:10,s:20); Writeln(F); Writeln(F,'Печать вещ. чисел в фиксированном формате'); Writeln(F,r:3:0); Writeln(F,r:5:3); Writeln(F,r:10:3) ; Writeln(F,r:11:7) ; Writeln(F,r:15:8) ; Writeln(F,r:25:8); Writeln(F); Writeln(F,'Печать вещ. чисел в плавающем формате'); Writeln(F,r:3); Writeln(F,r:5); Writeln(F,r:11); Writeln(F,r:17); Writeln(F,r:25); CloseFile(F); { Вывод созданного текстового файла в поле Memol. } Memo1.Lines.LoadFromFile('WritDemo.Dat'); end; end.
Результат работы приложения изображен на рисунке 1:
Рис.1. Результат работы приложения
Для текстовых файлов дополнительно к рассмотренным допускается использование следующих процедур и функций:
В заключение рассмотрения текстовых файлов перечислим их отличия от файлов типа file of Char:
Дополнительную информацию по текстовым файлам можно получить здесь.
На следующем шаге мы рассмотрим нетипизированные файлы.