Шаг 89.
Текстовые файлы

    На этом шаге мы рассмотрим работу с текстовыми файлами.

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


    В языке Object Pascal предопределенный идентификатор Text используется в большинстве случаев как имя свойства некоторых компонент (например TEdit.Text). Поэтому при объявлении текстовых файлов следует использовать квалифицируемое имя System.Text, с указанием имени модуля, где описан стандартный файловый тип 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) ;
будут эквивалентными.


    В стандартных Delphi-приложениях с формами и модулями обращения к файлам Input и Output (как явно, так и по умолчанию) вызывают ошибку ввода-вывода. Input и Output допустимо использовать только при компиляции приложений в консольном режиме.

    Во всех реализациях и версиях языка 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:

  1. Автоматическое преобразование числовых данных в цепочку символов при записи значений в файл, и обратное преобразование символов, являющихся числами, в числовое значение при выполнении операции чтения в переменные соответствующих числовых типов.
  2. Текстовые файлы не имеют прямого доступа.
  3. Записывать в текстовый файл и читать из текстового файла разрешается переменные только некоторых стандартных типов.
  4. Наличие признаков конца строки.
  5. Для чтения из текстовых файлов и записи в них разрешено исполызовние процедур Readln и Writeln, которые для остальных типов файлов не допускаются.

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

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




Предыдущий шаг Содержание Следующий шаг