Вернуться к «Delphi работа с файлами»
Если идти вниз по степени типизации файлов, то самым «типизированным» является текстовый файл. Он работает только с одним типом данных — строками. Далее идёт собственно типизированный файл — в нём данные могут быть любого, но строго одинакового типа (то есть одинаковой длины).
В нетипизированном файле информация тоже поделена на записи, но длина записи не обязательно должна соответствовать какому либо типу и задаётся программистом произвольно.
Функции и процедуры
AssignFile(f,’имя_файла’); «здесь f — переменная типа File»
Связывает файловую переменную с именем файла.
reWrite(f,N); Если файл не существует, то он создаётся. Если существует, то перезаписывается. N – длина записи в нетипизиованном файле в байтах.
reset(f,N); Открытие файла для чтения. Информация будет читаться порциями, равными N байт.
Function fileSize(f):integer – подсчитывает количество записей в файле.
Function filePos(f):integer — определяет текущую позицию указателя записей в файле.
Procedure seek(f,N); сместить указатель файла к позиции номер N
Procedure blockWrite(f,buf,count); в файл будет помещено count записей, каждая из которых длиной N байт, указанных в rewrite(f,N). Очевидно, что N*count должно быть меньше или равно длине буфера, иначе часть информации, содержащейся в буфере, пропадёт.
Следующее обращение к blockWrite запишет ещё такую же порцию информации.
Procedure blockRead(f,buf,count); из файла в буфер buf будет считано count записей, или N*count байт за одно прочтение, где N задаётся при открытии файла на чтение «reset(f,N)».
ПРИМЕР 1
/записать в нетипизированный файл и прочитать три целых числа
procedure TForm1.Button1Click(Sender: TObject);
var f:file; a,b,c,a1,b1,c1:integer;
begin
n:=sizeOf(integer);//размер целого — 4 байта
assignFile(f,’myFile.int’);
reWrite(f,n);//создать файл с записями длиной 4 байта (длина записи выбрана
4 байта, так как переменная целого типа имеет такую длину)
a:=1000;
b:=2000;
c:=3000;
BlockWrite(f,a,1);//создать первую запись
BlockWrite(f,b,1);//создать вторую запись
BlockWrite(f,c,1);//создать третью запись
closeFile(f);
reset(f,4);//открываем файл для чтения
blockRead(f,a1,1);//прочитать одну запись (то есть 4 байта)
Edit1.Text:=inttostr(a1);
blockRead(f,b1,1);
Edit2.Text:=inttostr(b1);
blockRead(f,c1,1);
Edit3.Text:=inttostr(c1);
closeFile(f);
reset(f,4);
seek(f,2);//установить указатель на считывание третьей записи (отсчёт от
нуля)
blockRead(f,d1,1);//читаем третью запись
Edit4.Text:=inttostr(d1);
closeFile(f);
end;
Результат работы программы:
ПРИМЕР 2
//Записать и прочитать из нетипизированного файла массив целых чисел
procedure TForm1.Button2Click(Sender: Tobject);
var f:file; a1,b1,c1,d1,n:integer; ar:array[1..3] of integer;
begin
n:=sizeOf(ar);//длина массива (количество байт, отведённых под массив)
assignFile(f,’myFile.int’);
reWrite(f,n);
ar[1]:=1000;
ar[2]:=2000;
ar[3]:=3000;
BlockWrite(f,ar,1);//формируем файл с одной записью. Запись имеет длину n
байт
closeFile(f);
reset(f,4);//открываем файл на чтения. Файл будет читаться порциями (записями) по 4
байта
blockRead(f,a1,1);//читаем первые 4 байта в переменную a1
Edit1.Text:=inttostr(a1);
blockRead(f,b1,1);//читаем следующие 4 байта в переменную b1
Edit2.Text:=inttostr(b1);
blockRead(f,c1,1);//читаем последние 4 байта в переменную с1
Edit3.Text:=inttostr(c1);
closeFile(f);
end;
ПРИМЕР 3
//этот пример имеет скорее теоретическое, чем практическое значение, однако на его базе возможны интересные построения.
//записываем в нетипизированный файл смешанные данные (данные разных типов).
//чтение производим в буфер (память, выделенная в куче через типизированный указатель на байт)
//для интерпретации данных после прочтения из файла необходимо знать структуру данных — какой был тип первой записи, тип второй записи и так далее.
procedure TForm1.Button5Click(Sender: Tobject);
type trec=record i:integer;r:real end; tar=array[1..2] of real;
var f:file;
n,nn,n1,n2,nnn,jj:integer;
rr:real;
ar,ar1:tar;
rec,rec1:trec;
p:pointer;//нетипизированный указатель
pb:pbyte; //типизированный указатель на данные типа byte
pj:pinteger; //типизированный указатель на данные типа integer
par:^tar; //типизированный указатель на данные типа tar
prec:^trec;//типизированный указатель на данные типа trec
begin
n:=sizeOf(rec);//длина переменной rec
n1:=sizeOf(jj);//длина переменной jj
n2:=sizeOf(ar);//длина переменной ar
assignFile(f,’myFile.int’);
reWrite(f,1);//открыть файл на запись. Длина одной записи — один байт.
rec.i:=1000;
rec.r:=200.123;
BlockWrite(f,rec,n);//записываем n байт, хранящихся в переменной rec
jj:=2000;
BlockWrite(f,jj,n1);//записываем n1 байт, хранящихся в переменной jj
ar[1]:=300.356;
ar[2]:=444.777;
BlockWrite(f,ar,n2);//записываем n2 байт, хранящихся в переменной ar
closeFile(f);//завершаем формирование файла
reset(f,1);//открываем файл на чтение, чтобы можно было определить его
размер
nnn:=Filesize(f);//определяем размер файла
reset(f,nnn);//устанавливаем размер записи при чтении равным длине файла
edit1.Text:= inttostr(nnn)+’ байт в файле’;
getMem(pb,nnn);//выделяем динамическую память под nnn байт. Адрес начала цепочки байт будет помещён в переменную-указатель pb
blockRead(f,pb^,1);//читаем один (первый) байт из файла и помешаем его в переменную. В качестве переменной использован разименованный указатель на байт. Этот байт — первый байт записи rec. Наша задача — передать адрес из указателя pb в указатель на запись prec. Так как типы указателей разные, то запрещено это делать напрямую. Но это можно сделать опосредованно через нетипизированный указатель.
p:=pb;//допустимое присваивание
prec:=p;//допустимое присваивание
jj:=(prec^).i;//разыменованование указателя
rr:=(prec^).r;//разыменованование указателя
edit2.Text:= inttostr(jj)+’ первое поле записи rec’;
edit3.Text:= formatFloat(‘0.###’,rr)+’ второе поле записи rec’;//выводим значение десятичного числа. Формат вывода — ‘0.###’. «0» — будет выведено любое количество цифр. «.» — выводится точка. «###» — будет выведено 3 знака после десятичной точки.
inc(prec);//увеличиваем значение указателя. Данная запись «prec» занимает в памяти 16 байт. Поэтому значение указателя prec будет увеличено на 16 (в десятичном выражении).
p:= prec;
pj:=p;//теперь указатель на целое установлен на начало цепочки байтов, кодирующих целое значение.
j:=pj^;//это присваивание сделано для наглядности
edit3.Text:= inttostr(j);
inc(pj);//увеличиваем указатель на 4 (длина целого значения)
p:=pj;
par:=p;//указатель установлен на начало массива
edit5.Text:= formatFloat(‘0.###’,(par^)[1])+’ первое значение массива ar’;
edit6.Text:= formatFloat(‘0.###’,(par^)[2])+’ второе значение массива ar’;
//(par^)[1] — разименование первой ячейки массива.
freeMem(pb,nnn);//освобождаем память (чтобы не было её утечки).
closeFile(f);
end;
В результате будем иметь:
ПРИМЕР 4
/пример, когда длина записи при создании файла и его чтении одинаковая
procedure TForm1.Button7Click(Sender: TObject);
type tar=array[1..3] of integer;
var f:file; aa,n,nn,n1,n2,n3,nnn,j,jj,jj1:integer; ar,ar1:tar;
begin
ar[1]:=100;
ar[2]:=200;
ar[3]:=300;
n:=sizeOf(ar);
edit1.Text:= inttostr(n)+’ длина массива’;
assignFile(f,’myFile.int’);
reWrite(f,3);
BlockWrite(f,ar,4);
nnn:=Filesize(f);
edit2.Text:= inttostr(nnn)+’ длина файла (записей)’;
closeFile(f);
reset(f,3);
blockRead(f,ar1,4);
edit3.Text:= inttostr(ar1[1])+’ ar[1]’;
edit4.Text:= inttostr(ar1[2])+’ ar[2]’;
edit5.Text:= inttostr(ar1[3])+’ ar[3]’;
closeFile(f);
end;
В результате:
ПРИМЕР 5
//пример, когда длина записи при создании файла и его чтении разная
procedure TForm1.Button6Click(Sender: TObject);
type tar=array[1..3] of integer;
var f:file; aa,n,nn,n1,n2,n3,nnn,j,jj,jj1:integer; ar,ar1:tar;
begin
ar[1]:=100;
ar[2]:=200;
ar[3]:=300;
n:=sizeOf(ar);
edit1.Text:= inttostr(n)+’ длина массива’;
assignFile(f,’myFile.int’);
reWrite(f,3);
BlockWrite(f,ar,4);
nnn:=Filesize(f);
edit2.Text:= inttostr(nnn)+’ длина файла’;
closeFile(f);
reset(f,4);
blockRead(f,j,1);
edit3.Text:= inttostr(j);//чтение первой ячейки массива
seek(f,2);
blockRead(f,j,1);//чтение третьей ячейки массива
edit4.Text:= inttostr(j);
closeFile(f);
end;
В результате:
***