AssignFile — Процедура Delphi


AssignFile — Процедура Delphi

Технология работы с файлами в системе Delphi требует определённого порядка действий:

  1. Прежде всего файл должен быть открыт. Система следит, чтобы другие приложения не мешали работе с файлом. При этом определяется, в каком режиме открывается файл — для изменения или только считывания информации. После открытия файла в программу возвращается его идентификатор, который будет использоваться для указания на этот файл во всех процедурах обработки.
  2. Начинается работа с файлом. Это могут быть запись, считывание, поиск и другие операции.
  3. Файл закрывается. Теперь он опять доступен другим приложениям без ограничений. Закрытие файла гарантирует, что все внесённые изменения будут сохранены, так как для увеличения скорости работы изменения предварительно сохраняются в специальных буферах операционной системы.

В Delphi реализовано несколько способов работы с файлами. Познакомимся со классическим способом, связанным с использованием файловых переменных. Файловая переменная вводится для указания на файл. Делается это с помощью ключевого слова File :

Описанная таким образом файловая переменная считается нетипизированной, и позволяет работать с файлами с неизвестной структурой. Данные считываются и записываются побайтно блоками, размер которых указывается при открытии файла, вплоть от 1 байт.

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

В качестве типа могут использоваться базовае типы, или создаваться свои. Важно только, чтобы для типа был точно известен фиксированный размер в байтах, поэтому, например, тип String в чистом виде применяться не может, а только в виде String[N], как указывалось в уроке Delphi 5.

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

Для текстовых файлов отдельно укажу, что тип файловой переменной в этом случае TextFile, а тип обычной — String.

Для открытия файла нужно указать, где он расположен. Для этого файловая переменная должна быть ассоциирована с нужным файлом, который определяется его адресом. Адрес файла может быть абсолютным, с указанием диска и каталогов (‘C:\Мои документы\Мои рисунки\FileName.ini’), или относительным, тогда он создаётся в папке с .exe файлом программы. Для задания относительного адреса достаточно указать имя файла с нужным расширением. Делается это оператором AssignFile :

AssignFile(SaveF, ‘C:\Мои документы\Мои рисунки\FileName.ini’);
AssignFile(SaveF, ‘FileName.ini’);

Теперь файл должен быть открыт.
Открытие файла оператором Rewrite приведёт воссозданию файла заново, т.е. существующий файл будет без предупреждения уничтожен, и на его месте будет создан новый пустой файл заданного типа, готовый к записи данных. Если же файла не было, то он будет создан.
Открытие файла оператором Reset откроет существующий файл к считыванию или записи данных, и его указатель будет установлен на начало файла :

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

Rewrite(SaveF, 1);
Reset(SaveF, 1);

Чтение файла производится оператором Read :

Запись в файл производится оператором Write :

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

if FileExists(‘FileName.ini’)
then Read(SaveF, SaveV);

Принудительно установить указатель на нужную запись можно оператором Seek(SaveF, N), где N — номер нужной записи, который, как и почти всё в программировании, отсчитывается от нуля:

Seek(SaveF, 49); — установка указателя на 50-ю запись.

При последовательном чтении из файла рано или поздно будет достигнут конец файла, и при дальнейшем чтении произойдёт ошибка. Проверить, не достигнут ли конец файла, можно оператором EOF (аббревиатура End Of File), который равен true, если прочитана последняя запись и указатель находится в конце файла:

while (not EOF(SaveF)) do
Read(SaveF, SaveV);

Для текстовых файлов вместо Read и Write используются операторы Readln и Writeln, умеющие определять конец строки. приведена процедура чтения текстового файла.

Оператор Truncate(SaveF) позволяет отсечь (стереть или, если хотите, удалить!) все записи файла, начиная от текущей позиции указателя, и до конца файла.

В конце работы с файлом его необходимо закрыть. Это делается оператором CloseFile(SaveF) ;

Теперь можно изменить программу из первой части урока, запоминающую своё положение на экране. Описание переменных опускаю, оно приведено на рисунке выше.

Создаём обработчик события Формы OnCreate со следующим содержимым:

procedure TForm1.FormCreate(Sender: TObject) ;
begin
AssignFile(SaveF, ‘Init.ini’) ;
if FileExists(‘Init.ini’) then
begin
Reset(SaveF) ;
Read(SaveF, SaveV) ;
Form1.Left := SaveV.X ;
Form1.Top := SaveV.Y ;
Form1.Caption:=SaveV.Caption ; //Наши переменные дополнительно сохраняют заголовок Формы!
end ;
end ;

Теперь необходимо создать обработчик события OnClose :

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction) ;
begin
Rewrite(SaveF) ; //Нет необходимости проверять наличие файла, создадим его заново!
SaveV.X := Form1.Left ;
SaveV.Y := Form1.Top ;
SaveV.Caption := Form1.Caption ;
Write(SaveF, SaveV) ;
CloseFile(SaveF) ;
end ;

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

AssignFile — Процедура Delphi

Процедура AssignFile( var Vf; FileName: string );

Описание
Процедура устанавливает ассоциативную связь между файловой переменной Vf и внешним файлом, имя которого определено параметром FileName. Все операции, производимые с файловой переменной, будут производиться со связанным с ней файлом. FileName — выражение типа string или PChar (если допускается расширенный синтаксис). Если в качестве имени файла указать пустую строку, то файловая переменная будет ассоциирована со стандартным файлом ввода (когда после AssignFile следует процедура Reset) или вывода (когда после AssignFile следует процедура Rewrite).

Клуб программистов

Delphi programming

Подписаться на рассылку:

AssignFile

связывает файл (TFile) с физическим файлом

|| 1 procedure AssignFile ( var FileHandle : TextFile; const FileName : string ) ;

|| 2 procedure AssignFile ( var FileHandle : File; const FileName : string ) ;

Описание:

Delphi процедура AssignFile назначает для файла (TFile) — физический файл. При подготовке для чтения или записи в этот файл. То есть связывает файл (TFile) с физическим файлом (двоичным или текстовым) для дальнейшей работы с ним. Под физическим файлом подразумевается файл на жёстком диске или другом внешнем носителе.

Пример кода:

var
myFile : TextFile;
text : string;

begin
// Try to open the Test.txt file for writing to
AssignFile(myFile, ‘Test.txt’);
ReWrite(myFile);

// Write a couple of well known words to this file
WriteLn(myFile, ‘Hello’);
WriteLn(myFile, ‘World’);

// Close the file
CloseFile(myFile);

// Reopen the file for reading
Reset(myFile);

// Display the file contents
while not Eof(myFile) do
begin
ReadLn(myFile, text);
ShowMessage(text);
end;

// Close the file for the last time
CloseFile(myFile);
end;

Не выполняется функция AssignFile

Доброго времени суток!

Программирую в Delphi несколько лет и никогда прежде при работе с этими же функциями с такой проблемой не сталкивался.

Собственно, мизансцена — написал простенькую программу в которой использовал функции управляющие возможностью записи данных в файл и чтением из него, всё работало и во время разработки, и при тестировании программы на всех компьютерах. кроме тех, где стоит Windows XP ( ). Стоило заставить её работать с файлом на XP — начал получать I/O error 102, на Windows 7 — срабатывает до сих пор без проблем.

Поскольку путь до той части программы, где она пишет в файл — неблизкий и Delphi на компьютере том нет, то отловив проблему и поняв что она связана с записью в файле — создал еще 1 проект, из 2х Button и 1 Memo, задача для этой второй программки проста:
1. Проверить, существует ли файл (думал беда в том, что по какой то причине он его не видит)
2. Связать переменную с файлом (AssignFile)
3. Открыть файл для записи (
4. Записать информацию в файл (в нашем случае — имя пользователя, просто первое что пришло в голову вбил, не суть)
5. Закрыть файл (старина CloseFile)

В отладчике заметил, что в переменную wtf ничего не записывается (скриншот приложил).

Товарищи — воистину в ступор вошёл: файл — существует, переменная — на месте, программа — компилируется (значит когда без существенных с точки зрения Delphi косяков), но при этом каждый раз доходя до Reset (Rewrite) — выскакивает это злобное I/O error 102
Мой препод мне всегда говорил, что лажает не программа — а разработчик или пользователь. Что ж, прошу помочь понять, где я облажался

11.08.2015, 12:36

AssignFile
Кусок кода var aFile: TextFile; naz:string; AssignFile(aFile, (naz)+’.txt’); .

Оператор AssignFile
Всем привет! У меня возник вопрос по использованию оператора AssignFile. Например есть кусочек.

AssignFile и access violation
Подскажите, в каких случаях может возникать ошибка access violation в строке с AssignFile? //.

Stack Overflow при AssignFile
Есть процедурка, которая создает временный файл. При передаче массива в 480000 элементов вылазит.

Альтернатива AssignFile, BlockRead, BlockWrite
Доброго времени суток. Появилась такая проблема. AssignFile не умеет хавать большие файлы, а мне.

11.08.2015, 12:45 2 11.08.2015, 12:47 3 11.08.2015, 13:21 [ТС] 4

Puporev, сижу с температурой и решил перебить код ручками. и слегка опечатался (:wall:), в коде программы — append, а не Reset (проверил только что).

Менять append на rewrite — тоже пробовал, это первое что пришло мне в голову, но увы — ничего на изменилось, ошибка сохранялась.

Код из программы:

northener — точно. я же Button жму. глупая ошибка, всё от лени и нежелания проходить полный путь от запуска основной программы до выполнения ею записи в файл, сейчас уберу if then и посмотрю что отладчик пишет в переменную, по результатам отпишусь

Илон Маск рекомендует:  Что такое код bccomp

Добавлено через 27 минут
Я прям даже не знаю, что и сказать. Ну проблему устранил и она была и близко не в AssignFile/Append и пр. .

После подсказки господина nortenerа — всё заработало на XP и я решил проверить основную программу, и там есть стадия, когда происходит перебор всех файлов и папок (с её подпапками) в заданной директории, с целью найти файлик с определённым расширением. Для простоты манипуляций я выполнял SetCurrentDir(ExtractFileDir(ptor))ptor как раз записан адрес директории, в которой ищет программа). А вот вернуть всё на место — я подзабыл.

В итоге — проблема была всё же в том, что файла не было в той директории, откуда он доставался и само собой банальный SetCurrentDir(ExtractFilePath(ParamStr(0))) — меня спас и всё теперь по фэншую:)
А тот факт, что сработало на Windows 7 и не сработало на Windows XP — банально не повезло, на Windows 7 я не прогонял программу по всем функциям за один запуск, а на Windows XP — одно и тоже запущенное приложение прогнал по всем возможностям его, в результате на одном из этапов директория сбивалась и связать переменную с несуществующим файлом — было уже никому не под силу :)

Тему закрывать могу как-то сам, или надо как-то попросить модераторов?

Назначение файла Delphi

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

Процедура AssignFile Delphi:

Задать имя файла позволит процедура AssignFile, которая связывает файловую переменную с определенным файлом. Общий вид процедуры AssignFile представляется так:

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

Delphi-Help

AssignFile

AssignFile

Описание

Процедура AssignFile назначает значение FileName значению FileHandle при подготовке к чтению или записи этого файла.

Версия 1
Берет тип переменной текстового файла как дескриптор. Когда файл открыт он обрабатывается как textfile.
Если имя файла пустая строка, то доступ к файлу осушествляется через стандартные потоки input и output.

Версия 2
Берет бинарный тип файла как дескриптор. Файл обрабатывается как двоичный файл.
В обоих случаях, когда файл открыт с помощью Append, Reset или ReWrite предполагается, что он находится в текущем каталоге.

Пример кода

var
myFile : TextFile;
text : string;

begin
// Попытка открыть файл Test.txt для записи
AssignFile (myFile, ‘Test.txt’);
ReWrite(myFile);

// Запись нескольких известных слов в этот файл
WriteLn(myFile, ‘Hello’);
WriteLn(myFile, ‘World’);

// Закрытие файла
CloseFile(myFile);

// Повторное открытие файла для чтения
Reset(myFile);

// Показ содержимого файла
while not Eof(myFile) do
begin
ReadLn(myFile, text);
ShowMessage(text);
end;


// Закрытие файла в последний раз
CloseFile(myFile);
end;

Примечание

FileHandle не должен быть перепутанным с дескриптором файла, используемым для файла низкого уровня, обращающегося с подпрограммами типа FileOpen и FileRead.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  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.

Илон Маск рекомендует:  Что такое код mb_ereg_search_getregs

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

AssignFile — Процедура Delphi

Текстовый файл отличается тем что он разбит на разные по длине строки, отделенные символами #13#10. Есть 2 основных метода работы с текстовыми файлами — старый паскалевский способ и через файловые потоки. У обоих есть преимущества и недостатки. Через потоки способ проще поэтому начнем с него.

Итак у всех потомков класса TStrings (TStringList, memo.Lines и т.п. ) есть методы записи и чтения в файл — SaveToFile, LoadFromFile. Преимущество — простота использования и довольно высокая скорость, недостаток — читать и писать файл можно только целиком.

1. Загрузка текста из файла в Memo:

2. Сохранение в файл:

3. А вот так можно прочитать весь файл в строку:

Паскалевский метод доступа

Для более тонких операций над текстовыми файлами прийдется освоить очень древний паскалевский способ.

Итак, для доступа к текстовым файлам используется переменная типа TextFile. До сих пор не совсем понимаю что это такое физически — что-то типа «внутреннего» паскалевского Handle на файл.

Итак чтобы ассоциировать файл на диске с переменной надо проделать следующие опрерации:

1) Определяем файловую переменную:

2) Ассоциируем ее:

3) Теперь надо этот файл открыть, есть 3 варианта:

  1. файла нет или он должен быть перезаписан, открытие для записи: Rewrite(f)
  2. файл есть и его надо открыть для чтения (с первой строки): Reset(f)
  3. файл есть и его надо открыть для дописования строк в конец: Append(f)

Как видите не хватает очень полезных функций таких как открытия файла для чтения с произвольной строки и для записи в файл произвольной строки. Но надо учесть, что так как длины строк разные, не существует никакого способа узнать физическое место начала например 1000 строки, не прочитав всю тысячу строк. Для записи ситуация еще сложнее — вставить строку означает перезаписать всю информацию после этой строки заново. Таким образом варианты только следующие:

  • Перезаписать весть файл
  • Читать с первой строки
  • Дописать что-то в конец
  • Читать и писать файл целиком (см. выше работу через TStrings)

В конце работы открытый файл нужно закрыть:

Теперь пусть у нас есть строковая переменная s для чтения строки из файла

Чтение предварительно открытого файла:

ReadLn(f, s) — будет прочитанна текущая строка и позиция чтения переведена на следующую позицию.

А как прочитать весь файл?

Хорошо, а если файл несколько метров есть ли способ поставить какой-нибудь ProgressBar или Gauge чтобы показывал сколько считанно? Есть, но не совсем прямой — не забыли, сколько строк в файле заранее мы не знаем, узнать можно только прочитав его весь, но показометер мы все-таки сделаем:

Теперь комментарии к коду.

  1. Функию GetFileSize я рсссмотрю после, она немного по другому подходит к чтению файла (кстати я знаю еще по крайней мере 3 способа ее реализации, поэтому не нужно указывать что это можно сделать легче, быстрее или просто по другому — просто давайте разберем это позже)
  2. Переменная i — все время указывает на количество байт которое мы считали — мы определяем длину каждой строки и прибавляем 2 (символы конца строки). Зная длину файла в байтах и сколько байт прочитано можно оценить и прогресс, но
  3. Если ставить изменение прогресса после каждой строки, то это очень сильно тормознет процесс. Поэтому вводим переменную j и обновляем прогресс например 1 раз на 1000 прочитанных строк
  4. Переменная Canceled — глобальная переменная. Поставьте на форму кнопку, в обработчике нажатия поставьте Canceled:=True; и нажатие кнопки прервет чтение файла.

Теперь как писать в текстовый файл:

Запись целой строки:

Запись кусочка строки(те следующая операция записи будет произведена в ту же строку):

Если переменная s содержит больше 255 символов (т.е. является длинной строкой), то таким способом ни фига не запишится, в файл вместо строки попадут 4 байта указателя на нее. Надо делать так:

Работа через WinAPI

Раздел написан Podval (примеры к сожалению на С++)

Любителям WinAPI посвящается. Функции FileOpen, FileSeek, FileRead. Возьмем форму, положим на нее кнопку, грид и Опен диалог бокс. Это для Билдера, но какая нам в данном случае разница?

Потренируемся еще. Функции FileExists, RenameFile, FileCreate, FileWrite, FileClose. Бросим на форму Save dialog box.

(с) Оба примера взяты из хелпа по Borland C++ Builder 5.

Первоисточник тот же.

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


В этом примере идет поиск в текущем каталоге и каталоге Windows

В дополнение к Дате/Времени

Для конвертации возвращаемого значения в TDateTime:

Теперь разберем типизированные файлы. Типизированный файл — это файл в котором записанны идентичные структуры. Например любой файл можно считать файлом байтов — т.е. можно его читать байт за байтом, можно перейти сразу к любому байту по его номеру, можно сразу узнать сколько байт в файле, можно заменить любой байт на другой не перезаписывая файл. Теперь все это в примерах:

Объявляем файл байтов:

Ассоциируем файловую переменную с физическим файлом:

Теперь мы можем либо перезаписать/создать файл:

Либо открыть существующий для чтения и записи:

Обратите внимание, что функция Reset хотя и имеет такой же формат как и для текстовых файлов, но открытый ей файл можно и читать и писать, в отличие от текстовых.

Теперь функции работы с файлом:

Все эти функции не работают с файлами большими 2 Gb.

После работы файл надо закрыть:

Приведенные выше механизмы будут работать с любым файлом, так как любой файл можно считать файлом байтов. Теперь где это можно использовать? В принципе везде, но в подавляющем большинстве случаев это будет очень неудобно, ведь скорость считывания при чтении по байтам будет на порядки более низкой чем другими способами. Однако в некоторых случаях этот способ может быть очень полезен. Например в программе вам надо заменить 100й байт файла на другой, или прочитать 100й байт файла, например во всяких читерских программах, при взломе и т.п. Здесь такой доступ будет весьма удобен. Гораздо более интересным представляется дальнейшее развитие технологии типизированных файлов (их еще лет 15 назад называли «Файлы прямого доступа»). Представим себе, что файл состоит не из байт а из более сложных структур. Например мы имеем некоторую информацию в виде:

Обратите внимание, что все элементы записи точно типизированны, нет ни длинных строк, ни открытых массивов, ни объектов, другими словами, заранее точно известно сколько именно байт будет занимать переменная этого типа. Объявим переменную этого типа:

и файл этого типа:

Теперь мы можем читать и писать сразу целую структуру, абсолютно так же как и если бы это был один байт:

Все остальные функции приведенные в предыдущей статье будут работать так же, только одно отличие — Seek и Size оперируют не с количеством байт, а с количеством записей.

Идем дальше. Есть такое понятие как нетипизированный файл. Это такой файл который содержит разнородные элементы. Например файл EXE — вначале он имеет заголовок, затем двоичный код, в конце какие-то ресурсы. Все части файла имеют разную длину и разную структуру. Тут уже обратится к произвольному элементу сложно, обычно надо вначале узнать где этот элемент находится, подчас это записано в предыдущем куске информации. Работа с такими файлами достаточно сложна и требует вручную разработки алгоритмов его чтения, но в связи гибкостью структуры и компактностью такие файлы составляют большинство. Для работы с нетипизированными файлами используют процедуры BlockRead и BlockWrite, которые позволяют читать/писать произвольное количество байт. Привожу пример пользования этими функциями из справки по Дельфи:

Этот код копирует из одного файла в другой. Замечания по поводу этого метода работы с файлами — плюсы — очень высокая скорость, особенно если размер буффера увеличить до 64kb-512kb, что позволит считывать файл достаточно большими кусками, чтобы обеспечить отсутствие простоев винчестера, к тому же обеспечивается очень высокая гибкость в работе. Минусы — сложность разработки, необходимость вручную писать все детали механизма чтения/записи и интерпретации данных.

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

Теперь разберем возможности работы потомка TStream — TFileStream — файловый поток. Этот класс был специально введен для работы с файлами. Для работы с файловым потоком Вам надо записать в Uses модули classes, Sysutils (classes — включает в себя собственно определение класса, Sysutils — некоторые константы необходимые для работы).

Вот пример записи/перезаписи файла:

Теперь небольшой разбор:

TFileStream.create — конструктор класса, его вызов требует указания имени файла и опций его открытия, следующие опции определены:

Теперь метод Write — этим методом в файл пишется любая информация из буфера любого типа, Вам надо указать только буффер и количество записываемых байтов. В данном случае используется переменная типа String в качестве буффера, но так как для длинных строк она представляет собой лишь указатель, то конструкция «pointer(s)^» заставляет обращаться именно к ее содержимому.

А вот этот код демонстрирует чтение файла с использованием файлового потока:

И пояснения к коду:

  1. Никаких проверок длину файла и его наличие здесь не делается — это демонстрационный код, а не готовая процедура чтения.
  2. Файл мы считываем в буффер типа PChar (с тем же успехом можно использовать массив или любой другой контейнер). Для тех кто не помнит — процедуры GetMem(p, 255) и FreeMem(p) — распределение памяти для строки и освобождение памяти.
  3. Метод потока Seek позволяет установить текущую позицию считывания/записи файла. Первый параметер — номер байта, второй — это от чего считать этот байт (у нас считать от начала файла), возможны варианты:
    • soFromBeginning — от начала файла
    • soFromCurrent — от текущей позиции считывания
    • soFromEnd — от конца файла (в этом случае номер байта должен быть отрицательным или равным нулю)
  4. Собственно считывание из потока осуществляется методом read, в котором указывается в качестве параметров буфер в который мы читаем и желаемое количество байт для чтения. Метод read является функцией, которая возвращает количество байт реально прочитанных из потока.
Илон Маск рекомендует:  Override - Директива Delphi

Заканчивая о файловых потоках хочу упомянуть о методе

CopyFrom который позволяет перекачивать информацию из одного потока в другой и о свойствах:

Size — размер файла
Position — текущая позиция чтения/записи потока

Работа с файловыми потоками весьма быстра, этот класс, являсь классом VCL, в то же время базируется на низкоуровневых функциях Windows, что обеспечивает очень высокую скорость работы и стабильность операций. К тому же многие компоненты и классы VCL поддерживаю прямое чтение и запись с файловыми потоками, что занчительно упрощает работу — например TStringList, TBlobField, TMemoField и другие.

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

Работа через Handle

Еще один способ работы с файлами — это открытие Handle на файл и работу через него. Тут есть 2 варианта — можно использовать функции Дельфи или использовать WinAPI напрямую.

При использовании функций Дельфи можно применять следующие функции:

FileOpen(FileName, fmOpenWrite or fmShareDenyNone) — функция открывает файл и возвращает целое цисло — Handle на файл. Параметры функции — имя файла и тип доступа (все типы доступа я перечислил ранее). Если файл успешно открыт то Handle должен быть положительным цислом, отрицательное число — это код ошибки.

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

FileClose(Handle: Integer) — закрывает файл

FileRead(Handle: Integer; var Buffer; Count: Integer): Integer;
FileWrite(Handle: Integer; const Buffer; Count: Integer): Integer;

Эти функции для чтения/записи файла, где Buffer любая переменная достаточного размера для чтения/записи куска информации (обычно типа PChar или массив), Count-количество байт, которое Вы желаете записать/прочитать. Функции возвращают количество байт которые реально были прочитанны или записаны.

Этот тип доступа к файлам применяется весьма редко. Дело в том что он практически дублирует соответствующие функции WinAPI и к тому же обычно работает несколько медленнее, чем например потоки. И все же использование функций FileOpen и FileClose не лишено привлекательности. Наряду с тем что эти функции намного легче в использовании соответствующих функций WinAPI (можете сравнить — FileOpen имеет 2 параметра, cooтветствующая функция WinAPI — CreateFile имеет 7 параметров, большая часть из которых реально требуется лишь в ограниченном числе случаев) этот путь доступа открывает возможность прямого использования всех функций WinAPI про работе с файлами, которые требуют Handle на открытый файл.

Дельфи предоставляет довольно широкие возможности по файловым операциям без использования механизмов открытия/закрытия файлов.

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

ChDir(NewCurrentPath: string); — изменяет текущий каталог (в среде Windows сие конечно не так актуально как в ДОС, но все же), прочитать же текущий каталог можно функцией GetCurrentDir, а текущий каталог для определенного драйва — GetDir.

CreateDir(const Dir: string): Boolean; — создает каталог. При этом предыдущий уровень должен присутствовать. Если вы хотите сразу создать всю вложенность каталогов используйте функцию ForceDirectories(Dir: string): Boolean; Обе функции возвращают True если каталог создан

DiskFree(Drive: Byte): Int64; — дает свободное место на диске. Параметер — номер диска 0 = текущий, 1 = A, 2 = B, и так далее

DiskSize(Drive: Byte): Int64; — размер винта. Обратите внимание на то что для результата этой и предыдущей функций абсолютно необходимо использовать переменную типа Int64, иначе макимум того что вы сможете прочитать правильно будет ограничен 2Gb

FileExists(const FileName: string) — применяется для проверки наличия файла

FileGetAttr(const FileName: string): Integer;
FileSetAttr(const FileName: string; Attr: Integer): Integer; — функции для работы с атрибутами файлов. Вот список возможных атрибутов:

RemoveDir(const Dir: string): Boolean; — удаляет папку(пустую)
DeleteFile(const FileName: string): Boolean; — удаляет файл
RenameFile(const OldName, NewName: string) — переименовывает файл

Информация о файле

Привожу пример функции которая собирает довольно большое количество информации о выбранном файле:

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

Теперь поговорим о поиске файлов. Для этой цели могут использоваться процедуры FindFirst, FindNext, FindClose, при участии переменной типа TSearchRec которая хранит информацию о текущем статусе поиска и характеристики последнего найденного файла.

Пример иллюстрирующий поиск всех файлов и каталогов в определенном каталоге:

Глава 2

Работа с файлами

Постановка задачи

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

Разработка формы

Создайте новый проект Delphi. Первым делом разработаем интерфейс программы. Изменим некоторые свойства главной формы. Прежде всего, присвойте соответствующее значение свойству Caption (заголовок формы) — например, Работа с файлами. Поскольку окно нашей программы должно всегда находиться поверх всех остальных окон, следует присвоить свойству FormStyle значение fsStayOnTop. Больше никаких свойств формы изменять не будем.

Разместите в левом верхнем углу формы, один над другим два компонента Label (метка) категории Standard. Для верхней метки присвойте свойству Caption значение Что:, а для второй — Куда:. Рядом с метками разместите по одному компоненту Edit (поле ввода) категории Standard. Присвойте свойству Name (имя) верхнего поля значение from, а свойству Name нижнего — значение where. Свойствам from.Text и where.Text присвойте пути по умолчанию, например: c:\1.txt и d:\2.txt.

Для того чтобы не утруждать пользователя копированием или ручным вводом путей размещения файлов, воспользуемся стандартными диалоговыми окнами открытия и сохранения файлов. Диалоговом окну открытия файла соответствует компонент OpenDialog категории Dialogs, а диалоговому окну сохранения — компонент SaveDialog той же категории. Разместим эти компоненты на форме. Для удобства изменим значение свойства OpenDialog1.Name на Open1, а значение свойства SaveDialog1.Name на Save1.

Справа от полей from и where разместим кнопки вызова диалогового окна обзора (компоненты Button категории Standard). Свойству Caption этих кнопок присвойте значение Обзор или просто поставьте точки. При желании, можете изменить размеры кнопок.

Разместите на форме под полем where компонент Label категории Standard и присвойте его свойству Caption значение Размер файла:. Справа от этой метки разместите еще один компонент Label, очистив для нее свойство Caption — эта метка будет отображать размер обрабатываемого файла.

Ниже разместим две кнопки (компоненты Button), присвоим их свойствам Caption значения Копировать и Вырезать. Под этими кнопками разместим компоненты, которые будут использоваться для выбора и удаления файлов: компонент Edit для ввода пути к файлу, кнопка вызова диалогового окна обзора и кнопка для удаления файла.

Свойству Edit1.Name присвоим значение Del, а свойству Text – путь по умолчанию. Кнопку Обзор разместим справа, а кнопку Удалить файл — под полем Del.

Полученная форма должна соответствовать рис. 2.1.

Рис. 2.1. Форма Работа с файлами

Разработка программного кода

Разработаем процедуру копирования файла. Это можно было бы реализовать средствами WinAPI, однако в этом случае процедура, хотя и была бы менее громоздкой, оказалась бы «привязанной» к системе, что для программ нежелательно, поэтому лучше воспользоваться библиотеками Delphi.

Для начала объявим нашу процедуру (назовем ее doit) как закрытый член класса формы:

Обработка файлов в среде Delphi

Лабораторная работа

На тему: «Обработка файлов в среде Delphi»

Задание 1: Создайте приложение, которое создает текстовый файл text1.txt и записывает в него текст, введенный пользователем в окно Edit, после чего закрывает файл.

Создайте форму и задайте для ее свойства Caption значение «Создание файла и вывод в него текста». Разместите на форме компоненты Edit1, Labbel1, Button1, как показано на рис. 6.1. Задайте значения для свойства Label1. Caption – «Введите текст», Button1. Caption – «Сохранить». Выровняйте компоненты и зафиксируйте их положение на форме.

Сохраните файлы модуля под именем main и проекта под именем TextEditFile в папке Обработка текстовых файлов.

Рис. 6.1 Пример формы проекта

Создайте процедуру обработки события кнопки «Сохранить», введите в окне Редактора кода следующий текст:

procedure TForm1. Button1Click (Sender: TObject);

Writeln (f, Edit1. Text);

Запустите приложение и введите в окно Edit следующее предложение – «Мой первый пример текста». Щелкните мышкой на кнопке «Сохранить» и закройте окно приложения.

Откройте окно Проводника Windows папку Обработка текстовых файлов, в которой сохранены файлы проекта. В списке файлов этой папки находится вновь созданный файл text1.txt. Дважды щелкните левой кнопкой мыши на имени файла text1.txt. Убедитесь, что это – тот самый текст, который введен в окне приложения. Откроется окно редактора Блокнот с этим файлом. Закройте окно редактора Блокнот и Проводник.

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

Создайте новое приложение (проект). Создайте форму «Чтение текста из файла в окно». На форме разместите компоненты Memo1, Label1, Button1, как показано на рис. 6.2. Задайте значения свойств Label1. Caption – «Текст из файла», Button1. Caption – «Прочитать текст из файла».

Для удаления текста Memo1 из компонента выберите в окне Инспектора объектов объект Memo1, затем на странице Свойства выберите свойсво Lines и в поле со значением Strings произведите двойной щелчок. После этого в окне StringListEditor удалите текст и щелкните мышью на кнопке ОК.

Для обеспечения возможности просмотра в окне Memo1 длинных текстов с использованием вертикальной полосы прокрутки в окне Инспектора объектов выберите свойство ScrollBars значение ssVertical. Выровняйте компоненты и зафиксируйте их положение на форме.

Рис. 6.2 Пример формы приложения

Создайте процедуру обработки события кнопки «Прочитать текст из файла», отредактируйте текст процедуры следующим образом:

procedure TForm1. Button1Click (Sender: TObject);

Понравилась статья? Поделиться с друзьями:
Кодинг, CSS и SQL