Основные типы файлов в Паскале
Подобно BASIC, в Паскале поддерживаются такие же три типа файлов -текстовые (строковые), типизированные (записеориентированные) и нетипизированные (двоичные).
Текстовые (строковые) файлы в Паскале
Текстовые файлы в Паскале относятся к дисковым файлам, каждая порция данных в которых представлена строкой переменной длины, содержащей не более 255 символов и завершающейся управляющими кодами ODOA. В отличие от QBasic, отдельные значения в файловой строке здесь не заключаются в кавычки и не разделяются запятыми. Единственным разделителем нескольких значений в пределах строки выступают пробелы, предусмотренные программистом при формировании содержимого текстового файла.
Для инициализации текстового файла необходимо объявить переменную соответствующего типа (f1:text;), связать ее с именем дискового файла (assign(f1, 'pas_txt') ;) и открыть для записи (rewrite(fl);), дозаписи (append(f1);) или для чтения (reset(f1),-). Закрывается текстовый файл Процедурой close (f1);.
Наиболее естественный профаммный способ создания текстового файла заключается в последовательной записи в него тем или иным способом сформированного значения какой-либо переменной типа string по оператору writein. На самом деле, текущую строку текстового файла можно формировать в несколько приемов, записывая туда данные последовательностью операторов write, завершая их оператором writein, который собственно и заносит признак конца строки.
Проще всего из текстового файла читать строку целиком по оператору readin в переменную типа string. Если в одной файловой строке находится несколько числовых значений, разделенных пробелами, то особых проблем при их извлечении не возникает. Требуется только соответствие количества и типов переменных считываемым значениям. Если из текущей строки текстового файла по оператору readin считывается меньшее количество значений, то следующий оператор readin будет извлекать данные с начала следующей строки, т. е. хвост предыдущей строки будет потерян. Если количество считываемых данных превышает длину текущей строки файла, то недостающие данные извлекаются из следующей строки. Однако, если числовая информация в текстовом файле перемежается со строковой, то вы можете столкнуться с описанным выше нежелательным поведением программы.
Программа 7_01. pas демонстрирует ошибку, напоминающую сбои в работе программы 7_01.bas. Отсутствие явных разделителей между символьной и числовой информацией приводит к непредусмотренному сдвигу данных (в переменную ь считывается первая файловая строка целиком) и попытке чтения числового значения ki из начала второй строки файла. Но Паскаль в отличие от Basic жестко контролирует соответствие типов и выдает сообщение invalid numeric format (Неправильный числовой формат) на первом же операторе readin.
Программа 7_01.pas
program bad_file;
uses Crt;
var
j,kl,k2:integer;
f:text;
b:string; begin
clrscr;
assign(f,'pas_txt') ;
rewrite(f);
for j :=1 to 10 do
begin
writeln('Строка',j:4,j*2:4);
writeln(f, 'Строка', j:4,j *2:4) ;
{или write(f,'Строка');
write(f,j:4);
writeln(j*2:4};
} end;
close(f);
writeln;
reset(f);
for j:=1 to 10 do begin
readln(f,b,kl,k2);
writeln(b,kl:4,k2:4);
end;
close(f);
readln;
end.
В программе 7_02.pas ошибка исправлена за счет изменения порядка числовых и символьных данных, но два текстовых значения в пределах одной строки ничем разделить нельзя. Заключение текста в одинарные кавычки ситуацию тоже не спасает.
Программа 7_02.pas
program txt_file;
uses Crt;
var
j,k1,k2:integer;
f:text;
b:string; begin
clrscr;
assign(f,'pas_txt');
rewrite(f);
for j:=1 to 10 do
begin
writeln(f,j:4,j*2:4,'Строка':8);
writeln(j:4,j*2:4,'Строка':8);
end;
close (f) ;
writeln;
reset(f);
for j:=1 to 10 do begin
readln(f,kl,k2,b);
writeln(kl:4,k2:4,b:8);
end;
close(f);
readln;
end.
Типизированные (записеориентированные) файлы в Паскале
Шаблон записи объявляется в разделе описания типов:
type
qq=record
a:string[6];
n:integer;
r:real;
end;
Для работы с типизированным файлом вводится файловая переменная (fl:fiie of qq;), которая связывается с дисковым файлом (assign(f1, 'pas_rec') ,-). Файл для ввода открывается оператором reset (f1), а для вывода — оператором rewrite (f1),. Обмен с записеориен-тированным файлом производится операторами read/write, в списках которых можно указывать только переменные типа "запись". Записи в типизированном файле нумеруются от 0 и имеется возможность прямого доступа к любой записи. Для этого перед операцией обмена указатель файла перемещается на начало нужной записи:
seek(f1,номер_записи);
Программа 7_03.pas формирует поля записи ь (строка из 6- ти символов, короткое целое число, вещественное число) и в цикле последовательно переписывает их на диск. Затем этот же файл открывается для ввода и его содержимое считывается в обратном порядке.
Программа 7_03.pas
program rec_file;
uses Crt;
type
qq=record
a:string[6];
n:integer;
r:real; end; var
f1:file of qq; j,kl: integer;
rec:qq; d:real;
begin clrscr;
assign (fl, 'pas__rec') ;
rewrite(fl);
rec.a:='Строка';
for j:=1 to 10 do begin
rec.n:=j;
rec.r:=sqrt(j);
write(fl,rec);
writeln(rec.a,rec.n:4,rec.r:10:4);
end;
close(fl);
writeln; reset(fl);
for j:=9 downto 0 do begin
seek(fl,j);
readffl,rec);
writeln(rec.a,rec.n:4,rec.r:10:4);
end;
readln;
end.
Нетипизированные(двоичные) файлы в Паскале
Для работы с нетипизированным (двоичным) файлом необходимо объявить файловую переменную (f1:fiдe;), связать ее с именем дискового файла и открыть его для записи (rewrite (f1,n);) или для чтения (reset(f1,n);). Параметр п здесь является необязательным, по умолчанию его значение равно 128. Задает он размер порции данных, участвующих в обмене, в байтах. Для обмена с двоичными файлами используются специальные процедуры blockread И blockwrite:
blockwrite(f1,buf,n_rec,vl);
blockread(f1,buf,n_rec,vl);
Здесь buf — массив (обычно типа byte), в котором находятся данные, либо подготовленные для записи на диск, либо считанные с диска. Параметр п_гес задает количество порций, участвующих в обмене. В переменную vl заносится фактическое количество записанных или считанных порций. Несовпадение между n_гес и значением vl при чтении обычно связано с некратностью длины файла и объемом считываемых данных. При выводе такое событие обычно возникает при исчерпании дисковой памяти. Чтобы обеспечить доступ к любому фрагменту данных в двоичном файле, необходимо воспользоваться процедурой перемещения указателя файла в нужную позицию:
seek(f1,n_rec);
В двоичном файле "записью" считается порция, размер которой был установлен в момент открытия файла, и нумеруются эти записи от 0.
Программа 7_04.pas выполняет в цикле вывод 10-ти порций данных, заготавливаемых в массиве buf (размер каждой порции — 15 байт). Обратите внимание на то, каким образом в этом массиве выделяются участки памяти для хранения разнотипных данных. Нетипизированный указатель р допускает присваивание адреса любого типа, а его значение может быть присвоено любому типизированному указателю. Для текста "строка", содержащего шесть символов, в массиве buf отводится семь байт с учетом указателя длины, предшествующего строковому значению.
Программа 7_04.pas
program bin_file;
uses Crt;
var
buf:array [1..15] of byte;
f1:file;
р:pointer;
рs:^string;
pk:^integer;
pr:^rеа1;
j:integer;
begin clrscr;
p:=@buf[l];
ps:=p;
p:=@buf[8];
pk:=p;
p:=@buf[10J;
pr:=p;
assign(f1,'pas_bin') ;
rewrite(fl,15);
ps^:='Строка';
for j:=1 to 10 do begin
pk^:=j;
pr^:=sqrt(j) ;
blockwrite(f1,buf,1);
writeln (рs^,р^: 4,рг^ : 10: 4) ;
end;
close(f1);
writeln;
reset(f1,15);
for j:=9 downto 0 do begin
seek(f1,j);
blockread(f1,buf,1);
writeln(рs^,рk^:4,pr^:10:4);
end;
close(f1);
readln;
end.