Работа с файлами и устройствами (ввод-вывод данных)

В систему Турбо Паскаль входит стандартный модуль System, содержащий описания разнообразных подпрограмм, предназначенных для работы с файлами и устройствами. Эти подпрограммы можно разделить на две категории - специализированные, рассчитанные на файлы определенных типов или действующие по-разному в зависимости от типа файла, и универсальные, позволяющие манипулировать любыми файлами. Рассмотрим здесь некоторые наиболее важные подпрограммы, относящиеся к первой группе. Как уже говорилось выше, текстовый файл представляет собой последовательность записей, содержащих строки переменной длины. Каждая строка завершается признаком конца строки EOLN (End Of LiNe), который образуется сочетанием двух символов - возврата каретки CR (Carriage Return), имеющего код ASCII 13, и перевода строки LF (Line Feed) с кодом ASCII 10. Файл в целом завершается признаком конца файла EOF, имеющим код ASCII 26. При вводе данных с клавиатуры признак EOLN воспроизводится клавишей Enter признак EOF - совместным нажатием клавиши управления Ctrl (Control) и клавиши Z.

Для считывания информации из текстового файла или с клавиатуры используются стандартные процедуры Read и ReadLn. Обращение к первой из них имеет вид

Read([<имя>,] <список ввода>);

Аргумент < список ввода > определяется образом:

< список ввода >:: = < переменная > [, < список ввода > ]

Здесь < переменная > - имя переменной любого числового, символьного или строкового типов. Процедура Read присваивает переменным, входящим в список ввода, значения, считываемые из файла или устройства, связанного с файловой переменной, которая задается необязательным аргументом <имя>. Если этот аргумент отсутствует, по умолчанию назначается стандартная входная переменная Input, автоматически связываемая с устройством CON (клавиатурой).

При вводе значения каждой переменной числового типа считывается последовательность символов, имеющая формат, соответствующий данному числовому типу. Если формат нарушается, фиксируется ошибка ввода-вывода и на экран выводится сообщение. Предшествующие значению символы пробела, табуляции и признак EOLN игнорируются. Считывание значения завершается, если очередным символом оказывается пробел, признаки EOLN или EOF.

При вводе значения символьной переменной считывается один байт, интерпретируемый как код ASCII, независимо от того, какой символ он представляет. Если это признак EOLN, переменной присваивается код ASCII 13, если EOF - код ASCII 26.

При вводе значения строковой переменной последовательность символов считывается вплоть до появления признака EOLN, на котором указатель файла останавливается (сам этот символ не считывается). Если длина считанной цепочки превышает ту, что указана в объявлении переменной, не уместившиеся в строке символы игнорируются. Если же длина меньше объявленной, незанятые позиции заполняются пробелами. Появление до завершения операции ввода признака EOF квалифицируется как ошибка, о которой выдается сообщение.

Таким образом, при нормальном ходе процедуры после ввода значения строковой переменной указатель файла в любом случае оказывается установленным на символ EOLN, в силу чего попытка с помощью Read ввести значение следующей переменной, расположенное в новой строке файла, всегда дает результат в виде пустой строки. Такова особенность процедуры Read, и если необходимо считать несколько строк подряд, следует воспользоваться процедурой ReadLn. Процедуре ReadLn предназначена для ввода информации только из текстовых файлов. Ее вызов имеет следующий формат:

ReadLn([<имя>,] [<список ввода>]);

Процедуре ReadLn передаются те же аргументы, что и процедуре Read, но список ввода при обращении к ней может отсутствовать. В этом случае все символы считываемой строки файла, включая признак EOLN, игнорируются, и указатель файла останавливается на первом символе следующей строки. При наличии списка ввода процедура ReadLn действует в основном так же, как и Read, но после считывания строковой переменной указатель файла устанавливается не на признаке конца строки EOLN (сам он не считывается), а на стоящем за ним первом символе следующей строки. Благодаря этому очередная операция ввода, выполняемая с помощью любой из двух рассмотренных процедур, дает правильный результат, поскольку считывание начинается с первого символа строки. Для вывода информации в текстовый файл или на дисплеи используются стандартные процедуры Write и WriteLn. Обращение к первой из них имеет вид

Write ([<имя>,] <список вывода>);

Аргумент < список вывода > определяется следующим образом:

< список вывода >:: = < выражение > [ < шаблон > ] [,< список вывода > ] < шаблон >:: =: < поле > [: < дробная часть > ]

Здесь < выражение > может иметь числовой, логический, символьный или строковый типы. Необязательный параметр < шаблон > определяет формат, в котором выводится значение выражения. Подпараметр <поле> указывает минимальную ширину поля, отводимого под это значение (по умолчанию 17 символьных позиций). Если значение независимо от его типа занимает меньше позиций, слева оно дополняется необходимым количеством пробелов, а если больше, то подпараметр игнорируется, и выводятся все символы значения. Подпараметр
< дробная часть > можно использовать совместно с подпараметром <поле> только при выводе вещественных чисел. Процедура Write переводит значения выражений, входящих в список вывода, из внутреннего формата в символьную форму (это необходимо только при обработке выражений логического и числовых типов) и записывает их в соответствующем формате в файл или выводит на устройство, связанное с файловой переменной, которая задается необязательным аргументом <имя>. Если этот аргумент отсутствует, по умолчанию назначается стандартная выходная переменная Output, автоматически связываемая с устройством CON (дисплеем).

Значение числового выражения вещественного типа в отсутствии подпараметра <дробная часть> выводится в экспоненциальном формате (в виде числа с десятичной точкой, буквы Е (от Exponent) и показателя степени, занимающего 4 позиции). Если отсутствует и подпараметр <поле>, под число отводится 23 позиции, если значение этого подпараметра меньше 10, число записывается в 10 позициях. При наличии подпараметра <дробная часть> значение числового выражения вещественного типа выводится в формате с фиксированной точкой. Этот подпараметр задает количество цифр после десятичной точки, причем, если он равен нулю, точка не пишется.

Значение выражения логического типа выводится в виде строк True или False.

После записи в файл значений всех выражений, содержащихся в списке вывода, процедура Write не помещает вслед за ними признак конца строки EOLN, вследствие чего в очередной операции вывода независимо от используемой процедуры информация продолжает писаться в ту же строку. Если же вывод очередной порции данных необходимо начинать с новой строки, вместо Write следует применять процедуру WriteLn. В отношении формата вызова и передаваемых аргументов процедуры Write и WriteLn идентичны:

WriteLn([< имя >,] < список вывода >);

Единственное различие заключается в том, что WriteLn, выполнив ту же цепочку действий, что и Write, записывает после выведенных значений признак конца строки EOLN, представленный последовательностью символов CR и LF. Благодаря этому следующая операция вывода всегда начинается с новой строки.

Кроме рассмотренных четырех процедур, при работе с текстовыми файлами часто применяются подпрограммы-функции SeekEOF и SeekEOLN. Формат вызова функции SeekEOF:

SeekEOF [(<имя>)]

Логическая функция SeekEOF принимает значение true, если указатель установлен на признак конца файла EOF. Во всех остальных случаях возвращается значение false. Если имя файловой переменной не указано, по умолчанию назначается входной файл Input. Формат вызова функции SeekEOLN:

SeekEOLN[(<имя >)]

Логическая функция SeekEOLN принимает значение true, если указатель файла установлен на признак конца строки EOLN. Во всех остальных случаях возвращается значение false. Если имя файловой переменной не указано, по умолчанию назначается входной файл Input.

Рассмотрим пример программы, которая позволяет ввести с клавиатуры дополнительную информацию в текстовый файл Letter.txt, уже существующий или создаваемый заново на диске d:, и вывести затем его содержимое на дисплей:

Program p14_3;

Var

MyFile: text;

Temp: string;

Label Exit;

Begin

Assign(MyFile,'d:\Letter.txt');

{$!-} {Блокировка контролях ошибок}

Append(MyFile); {Открытие файла для дозаписи}

{$!+} {Включение контроля ошибок}

If IOResult = 0 Then {Проверка наличия файла}

WriteLn(‘Файл подготовлен к работе');

Else

Begin

WriteLn ('Файл отсутствует');

Goto Exit; {Выход из программы в}

End; {случае отсутствия файла}

While not SeekEOF Do

Begin

ReadLn(Temp); {Считывание строки с клавиатуры}

WriteLn(MyFile,Temp);{3aпись строки в файл}

End;

Close(MyFile);

Reset(MyFile); {Открытие файла для считывания}

While not SeekEOF Do

Begin

ReadLn(MyFile,Temp); {Считывание строки из файла}

WriteLn{Temp); {Вывод строки на дисплей}

End;

Close(MyFile);

Exit:;

End.

Для считывания информации из типизированного файла используется стандартная процедура Read. Обращение к ней имеет вид

Read(<имя >, < список ввода >);

Обязательные аргументы <имя> и < список ввода > определяются так же, как и в процедуре Read для текстовых файлов. Отличие лишь в том, что < список ввода > может содержать только такие переменные, которые совпадают по типу с записями файла. Вывод информации в типизированный файл осуществляется с помощью стандартной процедуры Write, вызываемой следующим образом:

Write(< имя >, < список вывода >);

Обязательные аргументы <имя> и < список ввода > определяются так же, как и в процедуре Write для текстовых файлов, но < список ввода > может содержать только такие переменные, которые совпадают по типу с записями файла. Особенностью процедуры Write является возможность ее применения к типизированным файлам, открытым не только для записи процедурой ReWrite, но и для считывания посредством процедуры Reset. Это позволяет модифицировать содержимое файла, попеременно обращаясь, не закрывая его, к процедурам Read и Write. В отличие от текстовых файлов, записи-строки которых имеют переменную длину, типизированные файлы строятся из записей фиксированного размера, который задается неявным образом при объявлении типа файла. Благодаря этому наряду с последовательным доступом типизированные файлы допускают также произвольный, или прямой, доступ к записям по их номерам. При последовательном доступе после ввода-вывода очередной записи указатель файла автоматически устанавливается на следующую за ней запись. В силу этого выборку требуемой записи в последовательном режиме можно произвести, лишь обратившись предварительно ко всем предшествующим. Для того чтобы обратиться к нужной записи, минуя предыдущие, необходимо принудительно переместить указатель в соответствующую позицию. При работе с типизированными файлами эту операцию позволяет выполнить стандартная процедура Seek, обращение к которой имеет следующий вид:

Seek(< имя >, < номер >);

Аргумент < номер > - это выражение типа longint, задающее номер записи, на которую устанавливается указатель файла. Это приводит к тому, что ближайшая следующая за обращением к Seek операция ввода или вывода выполняется над записью с указанным номером (напомним, что первой записи файла соответствует нулевой порядковый номер). Проиллюстрируем на простом примере использование рассмотренных процедур для организации режима произвольного доступа к записям типизированного файла. В приведенной ниже программе во вновь созданный на гибком диске файл последовательно заносятся пять чисел типа longint. После каждой операции записи из файла считываются в обратном порядке все записанные к этому моменту числа и выводятся в стандартный файл Output (на дисплей).

program p14_4;

Var

MyFile: File of Longint;

I,K,Temp: Longint;

Begin

Assign(MyFile, 'd:\Data.dat');

ReWrite (MyFile); {Открытие файла для вывода}

For I:= 1 to 5 Do {и ввода записей}

Begin

Write(MyFile,I); {Вывод очередного числа в файл}

For K:= I-l downto 0 Do

Begin

Seek(MyFile,К); {Переустановка указателя файла}

Read (MyFile,Temp); {Считывание заданной записи}

Write(Temp); {Вывод считанной записи на экран}

End;

Seek(MyFile,I); {Восстановление указателя файла}

End;

End.

По окончании выполнения программы в стандартный выходной файл должна быть выведена цепочка чисел 121321432154321. Очевидно, в режиме последовательного доступа подобный результат получить невозможно. Обратим внимание на повторное применение процедуры Seek для восстановления указателя файла MyFile, Если не проделать эту операцию, по выходе из внутреннего цикла указатель будет вновь установлен на запись с нулевым номером.

program p14_5; {Вывод результата работы программы в файл rez.txt}

Var

RezFile:text;

Begin

clrscr;

assign(RezFile,'d:\rez.txt');

rewrite(RezFile);

Writeln(RezFile,'Rezultat = ');

{Основная программа}

close(RezFile);

end.


Понравилась статья? Добавь ее в закладку (CTRL+D) и не забудь поделиться с друзьями:  



double arrow
Сейчас читают про: