Шаг 61.
Нетипизированные файлы

    На этом шаге мы рассмотрим, что из себя представляют нетипизированные файлы.

    Turbo Pascal содержит понятие нетипизированных файлов, которые используются для доступа к любым дисковым файлам независимо от их структуры. В этом случае файл представляется как последовательность элементов произвольного типа. Для таких файлов указывается только размер элементов. Таким образом можно записать в нетипизированный файл значение любой переменной, имеющей заданный размер. При чтении из нетипизированного файла допускается произвольная интерпретация содержимого очередного элемента.

    Поясним сказанное на конкретном примере. При описании переменной файлового типа мы указываем тип элементов, из которых состоит файл. Например, описание: K: File Of Integer; говорит о том, что файл, который будет связан с этой файловой переменной, состоит из целых чисел. Это давно известно, заметите вы. Абсолютно правильно. Но что делает компьютер, "получив" такое описание? При каждом чтении элемента из такого файла он будет читать два байта (потому что размер переменной типа Integer два байта) и интерпретировать их содержимое как целое число. Попробуйте провести такой эксперимент: создайте программу, организующую файл и помещающую туда строки длиной, например, по 8 байт. После чего другой Pascal-программой откройте этот файл, интерпретируя находящиеся там значения как целые числа, и посмотрите, что получится.

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

    Переменная файлового типа, которая будет являться представителем нетипизированного файла в программе, описывается с помощью служебного слова File, например:


     Var
       Data  :  File;

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


     Reset (<имя файловой переменной>, <размер записи>);    .
Размер записи задается в байтах; если второй параметр опущен, то предполагается размер в 128 байтов.


    Замечания. 1. Для обеспечения максимальной скорости обмена длина записи должна быть кратной 512 байтам, что составляет размер сектора диска.
2. Общий размер файла может не быть кратен выбранному размеру записи (последняя запись может быть неполной). Для того, чтобы гарантированно обеспечить полное чтение всего файла, нужно установить размер записи равным единице.

    Для организации обмена с нетипизированными файлами предназначены две стандартные процедуры BlockRead и BlockWrite, каждая из которых имеет следующие модификации:


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

  BlockWrite ( <имя файловой переменной>; <буфер обмена>; 
                                       <количество записей>);  
     и 
  BlockWrite ( <имя файловой переменной>; <буфер обмена>; 
       <количество записей>, <реально записанное количество записей>);  .

    В качестве рабочего буфера для обмена используется переменная, которую необходимо описать в программе и размер которой не должен быть меньше размера записи, установленного в параметрах процедур Reset или Rewrite. Имя этой переменной указывается в вызовах процедур BlockRead и BlockWrite. В последний параметр помещается количество реально записанных или прочитанных записей. В обеих процедурах нужно следить за тем, чтобы размер буфера был равен произведению длины записи на количество используемых записей.

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

Проиллюстрируем применение нетипизированных файлов на конкретном примере: осуществить копирование содержимого одного файла в другой (файлы описать как нетипизированные). Приведем текст программы:
Program FileCopy;
Const
       RecSize = 512; {Размер буфера обмена}
Var
       FileIn, FileOut : File; {Копируем FileIn -> FileOut}
       NumRead,                { Число фактически считанных}
       NumWritten : Word ;     {и фактически записанных записей}
       Buf : array [1..RecSize] of char;   {Буфер обмена}
Begin
       Assign (FileIn, 'DAN1.TXT');  {Открываем файл-источник}
       Reset (FileIn, 1);   {Будем читать по одному байту}
       Assign (FileOut, 'DAN2.TXT'); {Открываем файл-приемник}
       Rewrite(FileOut,1);  {Будем записывать по одному байту}
       WriteLn ('Копируем файл');
       Repeat    {Цикл копирования}
         {Пытаемся прочитать сразу 512 байтов}
         BlockRead (FileIn,Buf, RecSize, NumRead);
         {Записывем столько байтов, сколько прочитали}
         BlockWrite (FileOut, Buf, NumRead, NumWritten);
         {Повторяем цикл пока есть что читать (NumRead<>0)}
         {и есть куда записывать (NumWritten=NumRead)}
       Until   (NumRead = 0) or (NumWritten <> NumRead);
       WriteLn ('Копирование закончено');
       Close (FileIn); 	        {Закрываем файлы}
       Close (FileOut);
End.
Текст этой программы можно взять здесь.

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

    Дополнительно допускается использование процедур и функций Seek, FileSize и FilePos для организации доступа к любой записи нетипизированного файла.

    На следующем шаге мы рассмотрим средства, позволяющие контролировать выполнение операций ввода/вывода.


Предыдущий шаг Содержание Следующий шаг