Нетипизированные файлы

В Pascal, кроме рассмотренных, существуют также нетипизированные файлы. Они совместимы со всеми типами файлов и используются тогда, когда тип элементов файла не важен (например, при копировании). Такие файлы описываются следующим образом:

var имя_файла: file;

Например, возможно такое описание:

var FileOneType: file;

Файл без типа представляется как последовательность элементов произвольного типа, но оговоренного размера. Это значит, что в файл можно записать значение любой переменной, имеющей заданный размер, а при чтении из такого файла допускается произвольная интерпретация содержимого очередного элемента.

Открываются файлы без типа теми же операторами Reset и Rewrite, но в этом случае имеется второй параметр — размер записи (элемента файла), заданный в байтах. Предварительно нужно с помощью оператора Assign связать внутреннее имя файла с внешним:

Assign(FileOneType, 'f.dat');   Reset(fileOneType, 1);

Второй параметр операторов Reset и Rewrite может быть опущен, что означает задание размера записи в 128 байт. Наибольшая скорость обмена данными обеспечивается при длине записи, кратной 512 байт (размеру сектора на диске).

Следует помнить, что если общий размер файла не кратен выбранном размеру записи, то последняя запись окажется неполной, и файл может быть прочитан не до конца. Этого не будет, если задать размер записи равным одному байту.

Обмен данными при работе с нетипизированными файлами осуществляется с участием рабочего буфера. В качестве которого используется объявленная в программе переменная. Ее размер должен быть достаточным для размещения данных, которые читаются (записываются) за один сеанс чтения (записи).

Перед чтением нетипизированный файл должен быть открыт с помощью процедуры Reset, а само чтение осуществляется процедурой BlockRead.

BlockRead(имя_файла, переменная_буфер, количество_записей)

Третий параметр — это количество записей, читаемых за один раз (тип Word).

При выполнении процедуры BlockRead данные помещаются в оперативную память, начиная с первого байта переменной, указанной в качестве второго параметра процедуры BlockRead. Поэтому переменная_буфер должна иметь размер, равный произведению, количества читаемых за один раз записей (третий параметр) и размера записи, заданного в процедуре Reset. В процедуре BlockRead возможно задание четвертого параметра (тип Word), в который помещается число фактически прочитанных записей.

Запись данных в нетипизированный файл производится только после его открытия с помощью процедуры Rewrite. Для записи данных используется процедура BlockWrite, которая имеет те же три (или четыре) параметра, что и BlockRead. При этом в переменную_буфер нужно предварительно поместить записи. Количество этих записей должно совпадать со значением третьего параметра процедуры BlockWrite, а размер — со вторым параметром процедуры Rewrite. В четвертом параметре процедуры BlockWrite (если он имеется) возвращается количество фактически помещенных в фал записей. Если на диске нет свободного места, то после выполнения процедуры BlockWrite значения третьего и четвертого параметров будут отличаться.

Если при чтении с диска окажется, что размер буфера будет меньше указанного выше или при записи на диск недостаточно свободного места, то при отсутствии четвертого параметра в процедурах BlockRead и BlockWrite будет зафиксирована ошибка. При наличии четвертого параметра ошибка не будет сгенерирована.

Работа с нетипизированными файлами на примере копирования файла:

const
  CountRead = 512; // кол-во читаемых записей.
   // При длине записи в 1 байт - размер буфера.
 
var
  file_in, file_out: file;
  name1, name2: string;
  num_read, num_write: word; // фактич. считанные/записанные записи
  buf: array[1..CountRead] of char; // буфер
 
begin
  Write('File 1: ');
  Readln(name1);
  Write('File 2: ');
  Readln(name2);
  Assign(file_in, name1);
{$I-}
  Reset(file_in,1);
{$I+}
  if IOResult <> 0 then begin
    WriteLn('Файл-оригинал не найден'); Halt
  end;
  Assign(file_out, name2);
  Rewrite(file_out, 1); // длина записи 1 байт
  repeat
    BlockRead(file_in, buf, CountRead, num_read);
    BlockWrite(file_out, buf, CountRead, num_write);
  until (num_read = 0) or (num_write <> num_read);
  writeln('Copying is completed');
  if num_read <> num_write then
    writeln('Not enough space');
  close(file_out); close(file_in);
end.