уважаемые посетители блога, если Вам понравилась, то, пожалуйста, помогите автору с лечением. Подробности тут.

Удивительно, но факт — запрос «delphi файлы» в Яндексе — это один из самых популярных запросов, касающихся Delphi. Популярнее только «delphi скачать» — видимо ещё не все слышали про такую штуку как Delphi Community Edition. Раз есть в Сети запрос — должен быть и ответ. Посмотрим, что получится в итоге.

Содержание статьи

Классика работы с файлами в Delphi — ключевое слово File

Этот способ, без преувеличения, можно назвать древнейшим способом работы с файлами в Pascal/Delphi. Однако и он до сих пор используется в работе, особенно, если это, например, лабораторная работа по информатике в школе или ВУЗе.

Для определения файловой переменной в Delphi/Pascal используется ключевое слово File. При этом, мы можем определить как типизированный файл, так и не типизированный, например:

type
  TPerson = record
    Name: string[20];
    Family: string[20];
  end;
 
var UntypedFile: File; //нетипизированный двоичный файл
    TypedFile: File of TPerson;//типизированный файл

Для типизированного фала мы можем задать тип данных фиксированного размера (ShortString, String[20], Integer, Single и так далее), например, мы можем определить такие типизированные файлы:

    IntFile: File of integer;
    StringFile: file of single;
    ShortStringFile: file of ShortString;

Или, как в примере выше использовать для указания типа запись (record), в которой все поля имеют фиксированный размер. Для типизированного файла нельзя указывать типы данных, размер которых не фиксирован, например, вот такие определения файловых переменных недопустимы:

type
  TIntArr = array of integer;
 
var StrFile: file of string; //недопустимо - размер string заранее не известен
    ArrFile: file of TIntArr;//недопустимо - размер динамического массива заранее неизвестен

Более того, даже компилятор Delphi укажет вам на ошибку, сообщив следующее:

[dcc32 Error] E2155 Type ‘string’ needs finalization — not allowed in file type

Определив файловую переменную можно приступать к работе с файлом. Алгоритм работы при этом будет следующим:

  1. Ассоциировать файловую переменную с файлом на диске
  2. Открыть файл
  3. Записать/Прочитать файл
  4. Закрыть файл

При этом, для типизированных и не типизированных файлов работа в части чтения/записи несколько различается в плане используемых методов.

Работа с типизированными файлами в Delphi

Рассмотрим несколько примеров работы с типизированными файлами в Delphi.
Для начала, рассмотрим вариант работы с типизированным файлом, например, представленном выше:

type
  TPerson = record
    Name: string[20];
    Family: string[20];
  end;
var TypedFile: File of TPerson;

Пример №1. Запись данных в типизированный файл Delphi

Запишем в наш файл две записи:

program example_1;
 
{$APPTYPE CONSOLE}
 
{$R *.res}
 
uses
  System.SysUtils;
 
type
  TPerson = record
    Name: string[20];
    Family: string[20];
  end;
 
var TypedFile: File of TPerson;
    Person: TPerson;
begin
  //связываем файловую переменную с файлом на диске
  AssignFile(TypedFile,'MyFile.txt');
  //открываем файл для записи
  Rewrite(TypedFile);
  //задаем имя/фамилию человека
  Person.Name:='Иван';
  Person.Family:='Иванов';
  //добавляем запись в файл
  Write(TypedFile, Person);
  //задаем имя/фамилию второго человека
  Person.Name:='Петр';
  Person.Family:='Петров';
  //записываем в файл
  Write(TypedFile, Person);
  //закрываем файл
  CloseFile(TypedFile);
 
  Readln;
end.

Рассмотрим методы, используемые в этом примере:

function AssignFile(var F: File; FileName: String): Integer;

Связывает файловую переменную F с внешним файлом FileName. В качестве второго параметра может задаваться как абсолютный путь к файлу, например, ‘C:/MyFile.txt‘, так и относительный, например, в коде выше файл будет создан рядом с exe-файлом.

procedure Rewrite(var F: File; [ RecSize: Integer]);

Создает новый файл и открывает его. Если внешний файл с таким именем уже существует, он удаляется и на его месте создается новый пустой файл. Если F уже открыт, он сначала закрывается, а затем воссоздается. Текущая позиция файла устанавливается в начале пустого файла.
F — это переменная, связанная с внешним файлом с использованием AssignFile. RecSize — это необязательное выражение, которое можно указывать, только если F является нетипизированным файлом (об этом ниже).

procedure Write([var F: File]; P1; [ ..., PN]); overload;

Используется для записи в типизированный файл. F — файловая переменная, P1..PN — это переменная того же типа, что и тип файла F.

procedure CloseFile(var F: File);

Прекращает связь между файловой переменной и файлом внешнего диска. F — это файловая переменная любого типа. Внешний файл, связанный с F, полностью обновляется, а затем закрывается, освобождая дескриптор файла для повторного использования.

В результате выполнения представленного выше кода, рядом с exe-файлом будет создан новый файл MyFile.txt, содержащий две записи, при этом, каждая запись будет иметь фиксированный размер, вне зависимости от фактических имени/фамилии.

Для того, чтобы в delphi не перезаписывать каждый раз файл, а добавлять в конец файла новые записи необходимо открывать типизированные файлы методом Reset. Рассмотрим пример добавления новых записей в типизированные файлы Delphi.

Скачать пример можно со страницы с исходниками

Пример №2. Добавление записей в типизированный файл Delphi

Рассмотрим такой пример Delphi:

program example_2;
 
{$APPTYPE CONSOLE}
 
{$R *.res}
 
 
uses
  System.SysUtils;
 
type
  TPerson = record
    Name: string[20];
    Family: string[20];
    Age: integer;
  end;
 
procedure ReadTypedFile;
const
  cStr = '%s %s %d';
var
  F: File of TPerson;
  Person: TPerson;
begin
  AssignFile(F, 'MyFile.txt');
  Reset(F);
  while not Eof(F) do
  begin
    Read(F, Person);
    Writeln(Format(cStr, [Person.Name, Person.Family, Person.Age]));
  end;
end;
 
procedure AppendTypedFile;
var
  F: file of TPerson;
  Person: TPerson;
begin
  AssignFile(F, 'MyFile.txt');
  // открываем файл для записи
  Reset(F);
  Seek(F, FileSize(F));
  // задаем имя/фамилию человека
  Writeln('Введите имя: ');
  Readln(Person.Name);
  Writeln('Введите фамилию: ');
  Readln(Person.Family);
  Writeln('Введите возраст: ');
  Readln(Person.Age);
  // добавляем запись в файл
  Write(F, Person);
  // закрываем файл
  CloseFile(F);
end;
 
var
  TypedFile: File of TPerson;
  Person: TPerson;
  DoAppend: integer;
 
begin
  if not FileExists('MyFile.txt') then
  begin
    AssignFile(TypedFile, 'MyFile.txt');
    // открываем файл для записи
    Rewrite(TypedFile);
    // закрываем файл
    CloseFile(TypedFile);
  end;
 
  // связываем файловую переменную с файлом на диске
  repeat
    Writeln('Добавить в файл запись: 1 - Да; 2 - Нет');
    Readln(DoAppend);
    case DoAppend of
      1: AppendTypedFile;
      2: break;
    end;
  until DoAppend = 0;
  //читаем все записи из типизированного файла
  ReadTypedFile;
  Readln;
end.

Разберемся с тем, что здесь делается. Во-первых, условие:

if not FileExists('MyFile.txt') then

проверяет, существует ли файл на диске. Метод FileExist имеет следующее описание:

function FileExists(const FileName: string; FollowLink: Boolean = True): Boolean;

FileName — имя файла, существование которого необходимо проверить. Второй параметр — FollowLink учитывается только при использовании символической ссылки. То есть, если нужно проверить только наличие символической ссылки на файл, то параметр FollowLink устанавливается в False, а если нужно проверить наличие и символической ссылки на файл и самого файла, то FollowLink устанавливается в True (значение по умолчанию).

Таким образом, в нашем примере, если файла нет на диске то он создается пустым. Далее выполняется цикл:

repeat
    Writeln('Добавить в файл запись: 1 - Да; 2 - Нет');
    Readln(DoAppend);
    case DoAppend of
      1: AppendTypedFile;
      2: break;
    end;
  until DoAppend = 0;

В этом цикле, если пользователь вводит 1, выполняется процедура AppendTypedFile, которая добавляет в файл очередную запись:

procedure AppendTypedFile;
var
  F: file of TPerson;
  Person: TPerson;
begin
  AssignFile(F, 'MyFile.txt');
  // открываем файл для записи
  Reset(F);
  //смещаемся в конец файла
  Seek(F, FileSize(F));
  // задаем имя/фамилию человека
  Writeln('Введите имя: ');
  Readln(Person.Name);
  Writeln('Введите фамилию: ');
  Readln(Person.Family);
  Writeln('Введите возраст: ');
  Readln(Person.Age);
  // добавляем запись в файл
  Write(F, Person);
  // закрываем файл
  CloseFile(F);
end;

Здесь, в принципе, весь алгоритм расписан в комментариях к процедуре.
Метод Reset не воссоздает файл снова, как Rewrite, а открывает его для чтения/записи (в случае двоичных файлов). Что касается метода Seek, то он имеет следующее описание:

procedure Seek(var F: File; N: Integer);

F — файловая переменная, ассоциированная с файлом на диске, N — номер записи в файле (первый номер — 0). Чтобы переместиться сразу в конец файла, мы сделали такой вызов:

Seek(F, FileSize(F));

где FileSize — это метод Delphi имеющий следующее описание:

function FileSize(var F: File): Integer;

В случае использования типизированных файлов эта функция возвращает количество записей в файле.

После того, как пользователь вводит что-то кроме 1 срабатывает метод ReadTypedFile — чтение всех записей из файла:

procedure ReadTypedFile;
const
  cStr = '%s %s %d';
var
  F: File of TPerson;
  Person: TPerson;
begin
  AssignFile(F, 'MyFile.txt');
  Reset(F);
  while not Eof(F) do
  begin
    Read(F, Person);
    Writeln(Format(cStr, [Person.Name, Person.Family, Person.Age]));
  end;
end;

Здесь мы, опять же, открываем файл методом Reset и в цикле while..do проходим по всем записям файла, пока не дойдем до конца. Здесь мы использовали два новых метода Delphi:

function Eof([var F: File]): Boolean; overload;

Eof возвращает True, если текущая позиция файла находится за последним символом файла или файл пуст. В противном случае Eof возвращает False.
По аналогии с методом Write, метод Read производит чтение очередной записи из файла и имеет следующее описание:

procedure Read(var F: File; V1; [ ..., VN]);

Результат работы нашего примера может быть следующим:

Ещё одним полезным методом для работы с типизированными файлами может быть процедура Truncate:

procedure Truncate(var F: File);

Удаляет все записи после текущей позиции файла. Вызовите Truncate в коде Delphi, чтобы текущая позиция файла стала концом файла (Eof (F) вернет true).
Рассмотрим пример использования этой процедуры.

Скачать пример можно со страницы с исходниками

Пример №3. Удаление последних записей типизированного файла в Delphi

Воспользуемся файлом, созданным в предыдущем примере и удалим из него две последние записи:

program example_3;
 
{$APPTYPE CONSOLE}
 
{$R *.res}
 
 
uses
  System.SysUtils;
 
type
  TPerson = record
    Name: string[20];
    Family: string[20];
    Age: integer;
  end;
 
procedure ReadTypedFile;
const
  cStr = '%s %s %d';
var
  F: File of TPerson;
  Person: TPerson;
begin
  AssignFile(F, 'MyFile.txt');
  Reset(F);
  while not Eof(F) do
  begin
    Read(F, Person);
    Writeln(Format(cStr, [Person.Name, Person.Family, Person.Age]));
  end;
end;
 
var
  TypedFile: File of TPerson;
  Person: TPerson;
  Count: integer;
  DoErase: integer;
begin
  AssignFile(TypedFile,'MyFile.txt');
  Reset(TypedFile);
  Count:=FileSize(TypedFile);
  if Count<2 then
    begin
      Writeln('Количество записей в файле меньше двух. Стереть все записи? 1 - Да; 2 - Нет');
      Readln(DoErase);
      if DoErase=1 then
        Truncate(TypedFile);
    end
  else
    begin
      Seek(TypedFile, Count-2);
      Truncate(TypedFile);
    end;
  //читаем все записи из типизированного файла
  ReadTypedFile;
  Readln;
end.

В этом примере мы делаем следующее:

  1. Открываем файл существующий AssignFile/Reset
  2. Определяем количество записей в файле (Count:=FileSize(TypedFile))
  3. Если количество записей меньше двух, то спрашиваем у пользователя стереть ли все записи и, в случае положительного ответа, вызываем метод Tuncate
  4. Если количество записей в файле больше двух, то смещаемся на нужную нам позицию в файле (Seek(TypedFile, Count-2)) и затираем две последние записи методом Truncate.
Скачать пример можно со страницы с исходниками

Подведем итог

Для работы с типизированными файлами в Delphi в самом общем случае нам необходимо выполнить следующую последовательность операций:

  1. Определить тип записей в файле — это могут быть стандартные типы данных Delphi с фиксированным размером: ShortString, integer, single и так далее или собственные типы данных, например, записи (record), но, в этом случае, главное условие — размер записи должен быть фиксированным.
  2. В коде Delphi/Pascal определить файловую переменную, используя ключевое слово file и, указав тип записей файла, определенный в пункте 1.
  3. Ассоциировать файловую переменную с внешним файлом на диске, используя метод AssignFile.
  4. Открыть файл для чтения/записи, используя методы Rewrite/Reset.
  5. Чтобы сделать в файл очередную запись используем метод Write, для чтения очередной записи из файла — используем метод Read.
  6. Закрыть файл методом CloseFile.

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

Функции и процедуры для работы с типизированными файлами в Delphi/Pascal

Метод Краткое описание
procedure AssignFile(var F: File; FileName: String)
Ассоциирует файловую переменную F с внешним файлом FileName. Переменная FileName может быть как именем файла, так и содержать полный путь к файлу на диске.
procedure CloseFile(var F: File);
Закрывает файл, ассоциированный с переменной F и освобождает переменную для дальнейшего использования.
function Eof(var F: File): Boolean;
Проверяет конец файла и возвращает True, если файловый указатель стоит в конце файла. В случае записи True означает, что очередной компонент будет добавлен в конец файла, при чтении — что файл прочтен полностью.
procedure Erase(var F: File);
Удаляет внешний файл, связанный с файловой переменной F. Перед удалением файла его необходимо закрыть методом CloseFile.
 
function FilePos(var F: File): Integer;
Возвращает текущую позицию в файле. В коде Delphi используйте FilePos для файловой переменной открытого файла, чтобы определить текущую позицию в файле. Если текущая позиция в файле находится в начале, FilePos возвращает 0.
 
function FileSize(var F: File): Integer;

 

Для типизированных файлов возвращает количество записей в файле.
procedure Read(var F: File; V1; [ ..., VN]);
Считывает из типизированного файла одну или несколько записей
procedure Rename(var F: File; Newname: String);
Переименовывает файл, ассоциированный с переменной F
procedure Reset(var F: File; [ RecSize: Integer]);
Открывает файл для чтения. Второй параметр RecSize указывается в случае использования нетипизированных файлов и указывает размер записи в файле в байтах
procedure Rewrite(var F: File; [ RecSize: Integer]);
Воссоздает файл. Если файл существует, то Rewrite его удалит, а затем создаст снова. RecSize используется для нетипизированных файлов
procedure Seek(var F: File; N: Integer);
Перемещает текущую позицию в файле к записи N (первая запись имеет номер 0)
procedure Truncate(var F: File);
Стирает из файла данные, расположенные за текущей позицией
procedure Write([var F: File]; P1; [ ..., PN]);
Записывает в файл F одну или несколько записей
5 1 голос
Рейтинг статьи
уважаемые посетители блога, если Вам понравилась, то, пожалуйста, помогите автору с лечением. Подробности тут.
Подписаться
Уведомить о
0 Комментарий
Межтекстовые Отзывы
Посмотреть все комментарии