Практика программирования (Бейсик, Си, Паскаль)

       

Основные типы файлов в Паскале


Подобно 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.




Содержание раздела