Файлы
Типизированные файлы
Такие файлы предназначены для обработки информации какого-то определенного типа. Это может быть и символ, и число. Если это строка, то её нужно объявлять с определенной длиной, например, так:
var s: string[50];
Кроме того, файл может принять пользовательский тип данных, например, запись (записи см. в следующей лекции). Поскольку компилятор знает длину типа в байтах, то он может организовать доступ к любому элементу типизированного файла по его порядковому номеру. Как только файл открыт, указатель устанавливается в начало файла и указывает на первый элемент с номером 0. После чтения или записи указатель сдвигается к следующему элементу. Это было бы невозможно, если бы компилятор заранее не знал размер каждого считываемого или записываемого элемента, поэтому и строка должна иметь строго определенный размер.
К типизированным файлам применимы следующие функции и процедуры:
FilePos - функция принимает параметр - файловую переменную, и возвращает позицию указателя, то есть, номер элемента, который будет обрабатываться при последующем чтении/записи. Пример:
FilePos(f1);
FileSize - функция, которая также принимает в качестве параметра файловую переменную, и возвращает количество элементов в файле. Пример:
FileSize(f2);
Read - процедура чтения данных из типизированного файла. В качестве параметров указывается файловая переменная, и одна или несколько переменных с таким же типом данных, как у файла. В эти переменные будет считан один или несколько (по количеству переменных) элементов, при этом указатель будет сдвигаться к следующему элементу. Пример:
Read(f1, MyRealPerem);
Write - процедура записи в типизированный файл. Как и у Read, у Write есть параметры - файловая переменная, и одна или несколько переменных с таким же типом данных, как у файла. Из этой переменной (этих переменных) будут браться данные, которые будут записаны в файл. После каждой записи указатель перемещается. Пример:
Write(f1, MyRealPerem);
Seek - процедура смещения указателя. Процедуре нужно указать файловую переменную и номер элемента, к которому нужно переместить указатель. Примеры:
Seek(f, 0); //указатель в начало файла Seek(f, 1); //указатель на второй элемент Seek(f, FileSize(f)); //указатель в конец файла
Еще раз замечу, что такие процедуры, как Readln, Writeln и Append работают только с текстовыми файлами, в типизированных или нетипизированных файлах их использовать нельзя.
Изучим работу с типизированными файлами на простом примере.
Откройте Lazarus с новым проектом. В Caption формы напишите "Типизированный файл" и сохраните проект в папку 23-02, не меняя имен формы, модуля и проекта.
На форму установите компонент TListBox. Полученный ListBox1 немного вытяните по высоте, чтобы в нем уместились 10 чисел. Справа установите одну под другой, две простых кнопки TButton, в Caption которых напишите, соответственно, "Сформировать файл" и "Читать из файла". У вас должна получиться примерно такая форма:
Идея такая. При нажатии на кнопку "Сформировать файл" мы с помощью функции Random будем формировать 10 случайных чисел, от 0 до 1000, и записывать их в типизированный файл. Файл у нас будет иметь тип Integer, то есть, под каждый элемент в файле будет выделено 4 байта. Таким образом, будет сформировано 10 элементов по 4 байта, в результате получится файл размером 40 байт.
При нажатии на кнопку "Читать из файла" мы будем по одному считывать эти элементы, и добавлять их в ListBox1. Таким образом, мы убедимся, что запись в типизированный файл, и чтение из него происходят без ошибок. Код первой кнопки следующий:
procedure TForm1.Button1Click(Sender: TObject); var f: File of integer; //файл типа integer i: integer; //счетчик для цикла begin AssignFile(f, 'mytypefile.dat'); Rewrite(f); for i:= 1 to 10 do //делаем 10 раз Write(f, Random(1000)); //записываем в файл случайное целое число CloseFile(f); end;
Код во многом вам знакомый, чтобы вы смогли с ним разобраться без надоедливых комментариев. Код второй кнопки:
procedure TForm1.Button2Click(Sender: TObject); var f: File of integer; k: integer; //для получения значений элементов begin //выходим из процедуры, если файла нет: if not FileExists('mytypefile.dat') then exit; ListBox1.Clear; AssignFile(f, 'mytypefile.dat'); //Открываем для чтения: Reset(f); //делаем от первого до последнего элемента: while not eof(f) do begin Read(f, k); //считываем очередной элемент в перем. k ListBox1.Items.Add(IntToStr(k)); //записываем это значение в ListBox end; CloseFile(f); end;
Код, я думаю, также не нуждается в дополнительных комментариях. Однако все же кое-что замечу. Поскольку файл типизированный, информация в него будет записана не в текстовом, а в двоичном виде, поэтому, открыв полученный файл простым текстовым редактором, вы не увидите там тех же чисел, что были у вас в ListBox1. Собственно, это даже хорошо - простой текстовый файл с данными пользователь может, ради интереса, и испортить неразумной попыткой редактирования, а вот в двоичный файл он лезть побоится.