Перечислим процедуры и функции для работы с текстовыми файлами.
SetTextBuf (f, buf, size) – процедура установки размера буфера. f: text, size: word; buf – тип задается. Должна выполняться перед открытием файла f. Буфер размещается в переменной Buf. Эта процедура служит для увеличения или уменьшения буфера ввода–вывода. Автоматическое значение размера буфера для текстовых файлов равно 128 байт. При интенсивном обращении к физическим файлам на диске рекомендуется увеличить это число до нескольких килобайт, что ускоряет процесс обращения к диску.
Flush (f) – процедура вывода содержимого буфера файла f в физический файл, не дожидаясь заполнения буфера до конца. f: Text.
Eoln (f) – функция возвращает True, если достигнут конец строки или конец файла. Тип Boolean.
SeekEoln (f) – функция возвращает True, если достигнут конец строки или конец файла, или перед ними стоят лишь пробелы и (или) символы табуляции. Тип Boolean.
SeekEof (f) – функция возвращает True, если достигнут конец файла, или перед ним стоят лишь пробелы, признаки концов строк и (или) символы табуляции.
Задача 6. Написать программу, распечатывающую на принтере информацию из текстового файла.
Program Task6;
Var FileName: String[20]; s: String;
f, f1: Text; code: byte;
Begin
Repeat
{Цикл выполняется до тех пор, пока имя файла вводится неверно}
Write(‘Введите имя файла’); Readln(FileName);
Assign (f, FileName);
{$I-} Reset (f); {$I+}
code:= IOResult;
If Code <> 0 Then Writeln(‘ Ошибка чтения файла!’)
Until Code = 0;
Assign (f1, ‘prn’);
Repeat
{Цикл выполняется до тех пор, пока имеются неполадки с принтером}
{$I-} Rewrite (f1); {$I+}
code:= IOResult;
If code <> 0 Then Writeln(‘ Включите принтер!’)
Until code = 0;
While Not Eof(f) Do
{Чтение из текстового файла по строкам и вывод на печать}
Begin Readln(f, s); Writeln(f1, s); End;
Close (f1); Close(f);
End.
Задача 7. В текстовом файле “Экзаменационные билеты” хранится 50 вопросов по изучаемому курсу. Каждый вопрос сопровождается коротким ответом. Вывести три вопроса и ответы к ним. Номера вопросов сгенерировать с помощью датчика случайных чисел.
В общем случае экзаменационный вопрос и ответ к нему могут содержать несколько строк. Чтобы отделить вопросы друг от друга, в текстовом файле пометим границу специальным символом, например, ‘******’. Чтобы считать порцию информации (вопрос и ответ к нему), необходимо организовать цикл чтения данных до тех пор, пока не встретится спецсимвол. Текстовый файл – это файл последовательного доступа. Чтобы вывести N-й вопрос и ответ к нему, необходимо предыдущие N–1 вопросов и ответов считать, не отражая считанную информацию на экране. Для этой цели создадим процедуру Jump. Чтобы не усложнять программу, спецсимвол отразим на экране, как и остальные считанные строки.
Program Task7;
Var s: String; i, j: integer; f: Text;
n: array [1..3] of integer;
L: Set Of 1.. 51; Ok: Boolean;
{s – строковая переменная для считывания информации из файла}
{f – файловая переменная}
{n – массив случайных чисел (номера вопросов)}
{L – множество целых чисел от 1 до 51}
{Ok – флажок. Вводится для определения окончания цикла
генерирования случайного числа.}
{Jump – процедура считывания порции информации.}
Procedure Jump;
Begin
While s<>’*****’ Do readln(f, s); s:=’’;
While s<>’*****’ Do readln(f, s); s:=’’;
End;
{Вывод считанной из файла информации на экран.}
Procedure Out_Text;
Begin
While s<>’*****’ Do Begin readln(f, s); Writeln(s); End; s:=’’;
End;
Begin
Randomize;
{Проверка наличия файла на диске.}
Assign (f, ‘bilet2.txt’);
{$I-} Reset (f); {$I+}
If IOResult <> 0 Then Begin Writeln (‘ Ошибка чтения файла!’); Halt End;
{Генерирование трех неповторяющихся чисел в интервале от 1 до 50}
L:= [];
For i:= 1 To 3 do
Begin
Repeat
n[i]:= random(50)+1;
If n[i] in L Then Ok:= False
Else Begin L:= L + [n[i]]; Ok:= True End;
Until Ok;
End;
{Считывание и вывод на экран содержимого трех экзаменационных билетов}
For i:= 1 To 3 Do
Begin
Reset (f);
For j:= 1 To n[i]-1 do Jump;
Out_Text;
Out_Text;
End;
End.
Нетипизированные файлы
Нетипизированные файлы манипулируют с данными, не задумываясь об их типе. Нетипизированные файлы – файлы, совместимые с данными любого типа, позволяющие обмениваться информацией блоками; обрабатываются быстрее, чем типизированные. С помощью нетипизированных файлов можно записывать на диск произвольные участки памяти ЭВМ.
Объявление такого файлового типа имеет вид:
f: File;
Принципы работы с нетипизированными файлами такие же, как и с типизированными. Нетипизированные файлы являются файлами прямого доступа. Файловая переменная должна быть связана с конкретным физическим файлом оператором Assign. Далее файл должен быть открыт для чтения или записи с помощью процедуры Reset(f) или Rewrite(f). В конце работы файл должен быть закрыт процедурой Close(f).
По умолчанию размер буфера передачи данных равен 128 байт. Можно явным способом указать иной размер буфера (чем он больше, тем быстрее происходит ввод–вывод), исходя из ресурсов памяти и удобства работы с данными. Для задания буфера надо после оператора Assign открывать файл расширенной записью процедур:
Reset (f, BufSize) и Rewrite (f, BufSize),
где f – переменная типа File; BufSize типа Word – задает число байтов, считываемых (или записываемых) из файла за одно обращение к нему.
Минимальный блок, который может быть записан или прочитан из файла, – 1 байт. Максимальный размер блока не может превышать 64К. Для обеспечения максимальной скорости обмена данными следует задавать длину, которая была бы кратна длине физического сектора дискового носителя информации. Фактически пространство на диске выделяется любому файлу порциями-кластерами, которые в зависимости от типа диска могут занимать два и более смежных секторов. Как правило, кластер может быть прочитан или записан за один оборот диска, поэтому наивысшую скорость обмена данными можно получить, если указать длину записи, равную длине кластера.
При работе с нетипизированными файлами могут применяться все процедуры и функции, доступные типизированным файлам, за исключением Read и Write. Их заменяют процедуры:
BlockRead (Var f: file; Var A; n: Word; Var result: Word) и
BlockWrite (Var f: file; Var A; n: Word; Var result: Word).
Эти процедуры осуществляют чтение в переменную A и запись из переменной A не компонентов файла или его строк, а блоков, состоящих из того количества байтов, которое определено для буфера файла f. Если n больше 1, то за одно обращение будет считано n емкостей буфера. Значение n < 1 не имеет смысла. Всегда должно выполняться условие:
n * BufSize < 64K.
Необязательный параметр result возвращает число буферов, считанное текущей операцией BlockRead. Аналогичный параметр в процедуре BlockWrite после каждой операции записи показывает число буферов, записанное этой операцией. Если операции ввода или чтения прошли успешно, то значения result будут равны соответствующим значениям n. Эти параметры могут использоваться для контроля выполнения BlockRead и BlockWrite.
Задача 8. Скопировать содержимое файла а1 в файл а2. Использовать нетипизированные файлы.
Размер блока нетипизированного файла в операторах Reset и Rewrite зададим равным 1. Количество записей, которые должны быть прочитаны или записаны за одно обращение к диску, в этом случае рассчитывается просто – это размер памяти, необходимой для переменной в операторе BlockRead. Если Buf массив из 10000 элементов типа Char, то количество записей, считанных за одно обращение, равно 10000. Окончание считывания определяется по последнему параметру процедуры BlockRead. При последнем вводе количество фактически обработанных записей либо равно 0, либо меньше n.
Program Task8;
Const nn = 10000;
Var a1File, a2File: String[20];
Buf: Array[1..nn] of Char; {Массив из 10000 символов.}
f, f1: File; code: byte; n, n1: Word;
Begin
Repeat
Write (‘Введите имя исходного файла’); Readln (a1File);
Assign (f, a1File);
{$I-} Reset (f,1); {$I+}
code:= IOResult;
If Code <> 0 Then Writeln(‘ Ошибка чтения файла!’)
Until Code = 0;
Write(‘Введите имя выходного файла’); Readln(a2File);
Assign (f1, a2File);
Rewrite (f1, 1);
Repeat
BlockRead(f, Buf, Sizeof(Buf), n);
BlockWrite(f1, Buf, n, n1);
Until (n = 0) or (n <> n1);
Close (f1); Close(f);
End.