Работа с текстовыми файлами в языке Ада

В Аде, как и в Nix-ах, все, с чем работает система - это файлы. Устройства ввода-вывода тоже рассматриваются как обычные файлы. Поэтому для файлового ввода вывода в Аде используются уже известные нам процедуры: Get(), Get_Line(), Put(), Put_Line();

Для работы с файлами в языке Ада существует тип File_Type, предопределённый в пакете Ada.Text_IO. У файла есть три режима доступа File_Mode:

In_File - чтение файла
Out_File - запись в файл
Append_File - запись в конец файла

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

with Ada.Text_IO; use Ada.Text_IO;
 
procedure main is
    My_File : File_Type;
    ch : Character;
begin
    --Создание файла в режиме записи
    Create(File => My_File, Mode => Out_File, Name => "MyFirstFile.txt");
 
    --Запись строки в файл с помощью Put
    Put(File => My_File, Item => "Первая строка!");
    --Переход на новую строку внутри файла
    New_Line(My_File);
    --Запись строки с помощью Put_Line
    Put_Line(File => My_File, Item => "Вторая строка!");
    --Закрытие файла
    Close(My_File);
 
    --Открытие файла в режиме чтения
    Open(File => My_File, Mode => In_File, Name => "MyFirstFile.txt");
 
    --Пока не достигнут конец файла
    while not End_Of_File(My_File) loop
        --Пока не встретился символ новой строки
        while not End_Of_Line(My_File) loop
            --Прочитать символ из файла
            Get(File => My_File, Item => ch);
            --Вывести прочитанный символ на экран
            Put(ch);
        end loop;
        --Если достигнут конец строки и мы вышли из цикла,
        --то пропускаем терминатор строки:
        Skip_Line(My_File);
        --Перевод курсора на новую строку
        New_Line;
    end loop;
    --Закрыть файл
    Close(My_file);
end main;

В Аде для обозначения конца строки используется так называемый терминатор строки, который не является обычным символом файла. Это значит, что конец строки (End_Of_Line) в Аде отличается от того, что принято в операционных системах Windows и UNIX. В этих системах для обозначения конца строки используется обычный символ (CR в UNIX, и символы: CR-LF в Windows), который может быть обработан обычными средствами символьной обработки.

Для того, чтобы при чтении из файла, процедура Get обработала этот терминатор, необходимо использовать уже известную нам процедуру Skip_Line (пропустить строку). То есть, дойдя до конца строки и встретив терминатор, программа просто отбрасывает этот терминатор как ненужный мусор.

Для работы с файлами чаще всего используются следующие процедуры:

  • Create - Создает файл с указанным именем и режимом использования. Если файл имеет строку null, то файл является временным и позднее будет удален.
  • Open - Открывает файл с указанным именем и режимом использования.
  • Delete - Удаляет указанный файл.
  • Reset - Возвращает позицию чтения (или записи) в начало файла (также может переустановить режим (фактически это переоткрытие файла в другом режиме)).

Наиболее часто используемые функции, возвращающие статус файлового обмена:

  • End_of_File - Возвращает True если курсор находится в конце текущего файла.
  • End_of_Line - Возвращает True если курсор находится в конце обрабатываемой строки текста.
  • Is_Open - Возвращает True если текущий файл открыт.
  • Mode - Возвращает режим использования текущего файла.
  • Name - Возвращает имя текущего файла.
  • Line - Возвращает номер текущей строки в файле (в которой находится курсор), который в данный момент обрабатывается.

Эти подпрограммы можно использовать как с параметрами, так и без. Если параметры не указаны, то будут обрабатываться данные со стандартного ввода-вывода:

  while not End_Of_File loop
    ...
  end loop;

Вообще в Аде все операции над файлами (сюда же я отношу и стандартные устройства ввода-вывода) производятся при помощи объектов типа File_Type. Есть несколько предопределенных объектов этого типа: Current_Input, Current_Output, Current_Error. Если для, например, Get() (или Get_Line()) не указывать File => "имя_файла", то по умолчанию будет задействован Current_Input (в нашем случае клавиатура). То есть, когда мы хотим прочитать с клавиатуры какой-нибудь символ, мы используем процедуру процедуру Get() следующим образом:

ch : Character;
...
Get(ch);
...

Такое использование процедуры Get() эквивалентно Get(Current_Input, ch).

Аналогично для процедур вывода (Put(), Put_Line()). Только для вывода по умолчанию задействуется объект Current_Output.

Если в системе определено устройство для вывода ошибок, то ошибки можно выводить на него:

Put(Current_Error, "Сообщение об ошибке");

Также в Аде можно переопределить/установить текущие устройства/файлы для ввода/вывода. Делается это с помощью процедур Set_Input, Set_Output и Set_Error. Например, пусть нам нужно, чтобы все сообщения выводились не на экран, а в файл "screen.txt", тогда мы просто создаем объект File_Type, связываем его с нашим файлом, и с помощью процедуры Set_Output устанавливаем это файл как устройство вывода по умолчанию:

New_Output : File_Type;
...
Create(New_Output, Out_File, "screen.txt"); --Создан и открыт для записи файл screen.txt
Set_Output(New_Output); --Файл screen.txt установлен в качестве устройства вывода по умолчанию

Если нужно после этого вернуть по умолчанию вывод на экран, то для этого нужно использовать Standard_Output:

Set_Output(Standard_Output);

Вот и все. Вывод результатов работы процедур Put()/Put_Line() будет осуществляться в  указанный файл. Если вывод нужно осуществить мгновенно, без задержек (т.н. буферизации), то можно использовать процедуру Flush().

Этим работа с файлами в языке Ада не ограничивается. Так как программист может создавать свои довольно сложные типы данных, то работать с ними через текстовые файлы будет не очень удобно. Поэтому для повышения производительности существуют так называемые бинарные (или двоичные) файлы. Для работы с ними используются другие пакеты и другие команды, хотя принцип остаётся тем же. Работу с бинарными файлами мы рассмотрим немного позднее.

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *