Лекция № 9

Тема: «Работа с файлами и папками»

 

План

1. Работа с папками

2. Команды управления файлами

3. Диалоги работы с файлами и папками

4. Извлечение частей из полного имени файла

5. Использование класса TStringList

6. Работа с папками и файлами с помощью функции WinAPI

 

1. Работа с папками

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

 

Определение имени папки

Для определения имени папки в Delphi есть несколько процедур, функций и свойств.

Функция

 

GetCurrentDir()

 

определяет имя текущей папки.

Создание папки

Для создания папки используют функцию вида:

 

CreateDir('имя папки')

 

Команда создает папку с указанным именем в текущей папке или на текущем диске.

 

Пример.

Для создания папки NewFolder в текущей папке используют команду вида:

 

CreateDir('NewFolder');

 

При указании имени папки допускается указание полного пути к ней. Например, допустима запись вида:

 

CreateDir('d:\Arhiv\NewFolder');

 

При этом необходимо, чтобы все папки, указанные в полном пути, существовали. А если нет, то папка создана не будет. В нашем случае, если на диске D не окажется папки Arhiv, то папка NewFolder создана не будет.

Для решения этой проблемы можно использовать команды:

 

CreateDir('d:\Arhiv');

CreateDir('d:\Arhiv\NewFolder');

 

В Delphi есть функция, которая позволяет изменить текущую папку на указанную. Функция имеет вид:

 

SetCurrentDir('имя папки');

 

Примеры.

 

SetCurrentDir('d:'); // переходим на диск d:

SetCurrentDir('Arhiv'); // на текущем диске d: переходим в папку Arhiv

SetCurrentDir('e:\Music'); // переходим в папку e:\Music

 

Если нужно создать цепочку вложенных друг в друга папок, то можно комбинировать функции SetCurrentDir() и CreateDir()

Пример. Создать папку с иенем d:\Arhiv\NewFolder и вернуться в папку с программой

 

SetCurrentDir('d:'); // переходим на диск d:

CreateDir('Arhiv'); // создаем папку Arhiv

SetCurrentDir('Arhiv'); // заходим в папку Arhiv

CreateDir('NewFolder'); // создаем папку NewFolder

SetCurrentDir(ExtractFilePath(Application.ExeName)) // переходим в папку с программой

 

В Delphi есть команда, которая позволяет создать всю цепочку папок, даже если они не существуют:

 

ForceDirectories('имя папки');

 

Пример.

 

ForceDirectories('d:\Arhiv\NewFolder');

 

Проверка существования папки

При попытке перейти в несуществующую папку или при попытке удалить несуществующую папку операция не будет выполнена успешно. Для корректной работы приложения необходимо предварительно проверить наличие указанной папки. Сделать это можно с помощью функции DirectoryExists()

 

if DirectoryExists('имя папки') then

  папка существует

else

  папка не существует;

 

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

 

// если папка существует

if DirectoryExists(ExtractFilePath(Application.ExeName) + '\Data') then

// переходим в эту папку

SetCurrentDir(ExtractFilePath(Application.ExeName) + '\Data');

 

Удаление папки

Для удаления папки существует функция вида:

 

RemoveDir('имя папки');

 

Указанная папка должна быть пустой. Если папка не пустая, то команда не выполнится.

Для удаления не пустых папок можно использовать функцию WinAPI ShFileOperation (см. Пункт 6 лекции).

 

2. Команды управления файлами

С помощью команд Delphi над файлами можно выполнять операции переименования, удаления, копирования, перемещения.

 

Копирование файла

Для копирования используют функцию вида:

 

CopyFile('файл-источник',’файл-приемник’, true);

 

Перед копированием можно проверить наличие файла-источника на диске и наличие папки файла приемника.

Пример. Скопировать файл primer.txt в файл d:\Files\text.txt

 

// если исходный файл существует

if FileExists('primer.txt') then

begin

// если существует папка назначения

if DirectoryExists('d:\Files') then

// копируем файл в указанную папку

CopyFile('primer.txt', 'd:\Files\text.txt', true)

// если папка назначения не существует

else

// выдаем сообщение с ошибкой

Application.MessageBox('Папка назначения не существует','Ошибка копирования', mb_ok + mb_iconstop);

end

// если файл не существует

else

// выдаем сообщение об ошибке

Application.MessageBox('Файл не существует','Ошибка копирования', mb_ok + mb_iconstop);

 

В рассматриваемом примере мы копируем конкретный файл по конкретному пути. Рассмотрим случай, когда пользователь самостоятельно задает файл и папку назначения.

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

 

// если исходный файл существует

if FileExists(Edit1.Text) then

begin

// если существует папка назначения

if DirectoryExists(Edit2.Text) then

// копируем файл в указанную папку под тем же именем

CopyFile(PChar(Edit1.Text), PChar(Edit2.Text + '\' + Edit1.Text), true)

// если папка назначения не существует

else

// выдаем сообщение с ошибкой

Application.MessageBox('Папка назначения не существует', 'Ошибка копирования', mb_ok + mb_iconstop);

end

// если файл не существует

else

// выдаем сообщение с ошибкой

Application.MessageBox('Файл не существует','Ошибка копирования', mb_ok + mb_iconstop);

 

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

 

Переименование (перемещение) файла

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

 

RenameFile('имя файла', 'новое имя файла');

 

Как и при копировании нужно проверять наличие файла и папки на диске.

Пример. Переименовать файл primer.txt в файл text.txt

 

// если файл существует

if FileExists ('primer.txt') then

// переименовываем файл

RenameFile('primer.txt', 'text.txt');

 

С помощью данной команды можно перемещать файл в другую папку.

Пример. Переместить файл primer.txt в папку d:\Files

 

// если исходный файл существует

if FileExists( 'primer.txt') then

begin

// если существует папка назначения

if DirectoryExists('d:\files') then

// перемещаем файл в указанную папку

RenameFile('primer.txt', 'd:\Files\primer.txt')

// если папка назначения не существует

else

// выдаем сообщение с ошибкой

Application.MessageBox( 'Папка назначения не существует','Ошибка перемещения', mb_ok + mb_iconstop);

end

// если файл не существует

else

// выдаем сообщение с ошибкой

Application.MessageBox('Файл не существует','Ошибка перемещения', mb_ok + mb_iconstop);

 

Можно одновременно перемещать и переименовывать файл, если в новом имени файла указать не только новую папку, но и новое имя файла. Так в рассмотренном выше примере команда переименования могла иметь вид:

 

RenameFile('primer.txt','d:\Files\ text.txt');

 

Как видно файл primer.txt не только перемещается в папку d:\Files, но и переименовывается в файл с именем text.txt.

Пример. Пусть пользователь самостоятельно задает имя исходного файла в поле Edit1 и папку для перемещения в поле Edit2. В этом случае команда переименования может иметь вид:

 

// если исходный файл существует

if FileExists(Edit1.Text) then

begin

// если существует папка назначения

if DirectoryExists(Edit2.Text) then

// перемещаем файл в указанную папку под тем же именем

RenameFile(Edit1.Text,Edit2.Text + '\' + Edit1.Text)

// если папка назначения не существует

else

// выдаем сообщение с ошибкой

Application.MessageBox('Папка назначения не существует','Ошибка перемещения', mb_ok + mb_iconstop);

end

// если файл не существует

else

// выдаем сообщение с ошибкой

Application.MessageBox('Файл не существует','Ошибка перемещения', mb_ok + mb_iconstop);

 

В отличие от функции CopyFile () при переименовании не нужно содержание компонентов конвертировать при помощи функции PChar ().

 

Удаление файла

Для удаления файла используют функцию

 

DeleteFile('имя файла');

 

Перед удаление целесообразно проверить наличие файла на диске.

Пример. Удалить файл primer.txt

 

// если исходный файл существует

if FileExists('primer.txt') then

// удаляем файл

DeleteFile('primer.txt');  

 

3. Диалоги работы с файлами и папками

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

Компоненты OpenDialog - диалог «Открыть файл» и SaveDialog - диалог «Сохранить как» используются чаще всего в большинстве приложений. Все свойства этих компонентов одинаковы, только их содержание немного разное для открытия и сохранения файлов. Основное свойство, в котором возвращается в виде строки выбранный пользователем файл - FileName. Значение этого свойства можно задать и перед обращением к диалогу. Тогда оно появится в диалоге в качестве значения по умолчанию в окне Имя файла.

Типы файлов, появляющихся в диалоге списке Тип файла, задаются свойством Filter. В процессе проектирования это свойство проще задать с помощью редактора фильтров, который вызывается нажатием кнопки с тремя точками рядом с именем этого свойства в Инспекторе Объектов. При этом открывается окно редактора. В его левой панели Filter Name укажите тот текст, который увидит пользователь в списке диалога. В правой панели Filter записываются разделеные точкой с запятой шаблоны фильтра.

После выхода из окна редактирования фильтров заданные вами шаблоны появятся в свойстве Filter в виде строки. В этой строке тексты и шаблоны разделяются вертикальными линиями.

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

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

Свойство InitialDir определяет начальный каталог, который будет открыт в момент начала работы пользователя с диалогом. Если значение этого свойства не задано, то открывается текущий каталог или тот, который был открыт при последнем обращении пользователя к соответствующему диалогу в процессе выполнения приложения.

Свойство DefaultExt определяет значение расширения файла по умолчанию. Если значение этого свойства не задано, пользователь должен указать в диалоге полное имя файла с расширением. Если же задать значение DefaultExt, то пользователь может писать в диалоге имя без расширения. В этом случае будет принято заданное расширения.

Свойство Title позволяет задать заголовок диалогового окна. Если это свойство не задано, окно открывается с заголовком, определенным в системе. Но вы можете задать и свой заголовок.

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

 

ofAllowMultiselect

Позволяет пользователю выбирать несколько файлов

ofCreatePrompt

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

ofEnableIncludeNotify

Позволяет посылать в диалог сообщения.

ofEnableSizing

Позволяет пользователю изменять размер диалогового окна.

ofExtensionDifferent

Этот флажок, значение которого можно прочитать после выполнения диалога, показывает, что расширение файла, выбранного пользователем, отличается от DefaultExt.

оfFilеМustExist

В случае, если пользователь написал имя несуществующего файла, появляется сообщение об ошибке.

оfHideReadOnly

Удаляет из диалога индикатор «Открыть только для чтения»

оfNoChangeDir

После щелчка пользователя на кнопке ОК восстанавливается текущий каталог, независимо от того, какой каталог был открыть при поиске файла.

ofNoDereferenceLinks

Запрещает переназначать клавиши быстрого доступа в диалоговом окне.

ofNoLongNames

Отражаются только не более 8 символов имени и трех символов расширения.

оfNоNetwоrkButton

Убирает из диалогового окна кнопку поиска в сети. Действует только, если флаг ofOldStyleDialog включен.

ofNoReadOnlyReturn

Если пользователь выбрал файл только для чтения, то генерируется сообщение об ошибке.

ofNoTestFileCreate

Запрещает выбор в сети защищенных файлов и недоступных дисков при сохранении файла.

ofNoValidate

Не позволяет писать в именах файлов неразрешенные символы, но не мешает выбирать файлы с запрещенными символами.

ofOldStyleDialog

Создает диалог выбора файла в старом стиле

ofOverwritePrompt

В случае, если при сохранении файла пользователь написал имя существующего файла, появляется сообщение, что файл с таким именем существует, и спрашивается разрешения пользователя переписать существующий файл.

ofPathMustExist

Генерирует сообщение об ошибке, если пользователь указал в имени файла несуществующий каталог.

ofReadOnly

По умолчанию устанавливает индикатор «Открыть только для чтения» при открытии диалога.

ofShareaWare

Игнорирует ошибки нарушения условий коллективного доступа и позволяет, несмотря на них, делать выбор файла.

ofShowHelp

Отражает в диалоговом окне кнопку Справка.

 

Несмотря на многочисленность опций в свойства Options, их начинает не хватать по мере развития Windows. Поэтому, начиная с Delphi 6, в диалоги введена еще одно свойство - OptionsEx. В это множество по мере развития Windows и Delphi будут включаться новые опции. Пока OptionsEx содержит только одну опцию:

 

оfExNоPlaceBar

Запрещает появление в диалоге полосы, обеспечивает доступ к папкам История, Рабочий стол и т.п.

 

По умолчанию все перечисленные опции в свойствах Options и OptionsEx, кроме ofHideReadOnly, выключены. Но, как видно из их описания, многие из них полезно включить перед вызовом диалогов.

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

Добавьте на форму компонент Savedialog. Задайте для него свойства:

Filter: FilterName = Текстовые файлы, Filter = * .txt;

DefaultExt = txt

 

Код расчета может иметь вид:

 

// описываем переменную для расчеты суммы

var rez: real;

begin

// если пользователь указал имя файла и щелкнул кнопку ОК

if SaveDialog1.Execute then

begin

// Считаем сумму

rez := StrToFloat(Edit1.Text) + StrToFloat(Edit2.Text);

// очищаем поле memo

Memo1.Clear;

// в поле memo формируем текст

Memo1.Lines.Add('Исходные данные:');

Memo1.Lines.Add('- первое число =' + Edit1.Text);

Memo1.Lines.Add('- второе число =' + Edit2.Text);

Memo1.Lines.Add('Сумма' + FloatToStr(rez));

// сохраняем содержимое поля memo в указанный файл

Memo1.Lines.SaveToFile(SaveDialog1.FileName);

end;

end;

 

Вызов диалога выбора папки

В некоторых программах необходимо задавать имя папки. Для этого используется специальный диалог вида:

 

 

Для отображения такого диалога необходимо:

 

- подключить модуль FileCtrl;

- описать строковую переменную для сохранения имени выбранной папки;

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

 

//описываем переменную для сохранения имени папки

var s:string;

. . .

//вызываем диалог и передаем в него имя переменной

//если папка в диалоге не выбрана

//код дальше не выполняется

if not SelectDirectory('Заголовок окна','', s, [sdNewUI, sdNewFolder]) then exit;

. . .

//код, выполняемый если папка выбрана

 

Пример. Пусть на форме имеется поле Memo1. Сохраним его содержимое в файл text.txt. При этом папку для сохранения зададим с помощью диалога выбора папки.

 

Подключим модуль FilECtrl.

 

Для кнопки сохранения напишем код:

 

procedure TForm1.Button1Click(Sender: TObject);

//описываем переменную для сохранения имени папки

var s:string;

begin

    //вызываем диалог и передаем в него имя переменной

    //если папка в диалоге не выбрана

    //код дальше не выполняется

    if not SelectDirectory('Выберите папку','',s, [sdNewUI, sdNewFolder]) then exit;

    //сохраняем поле Memo1 в файл text.txt в папку с именем из переменной s   

    Memo1.Lines.SaveToFile(s+'\text.txt');

end;

 

4. Извлечение частей из полного имени файла

Зная полный путь к файлу, из него можно вычленить какую-либо часть пути с помощью функций:

 

ExtractFileDrive('имя файла') - выделяет имя диска из полного имени файла

ExtractFilePath('имя файла') - выделяет полное имя папки из полного имени файла

ExtractFileName('имя файла') - выделяет имя файла из полного имени файла

ExtractFileExt('имя файла') - выделяет расширения из полного имени файла.

 

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

 

Application.ExeName

 

Следовательно имя папки с програмой определяется так:

 

ExtractFilePath(Application.ExeName)

 

5. Использование класса TStringList

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

Пример

 

// описываем переменную

var t: TStringList;

. . .

// создаем экземпляр класса

t := TStringList.Create;

 

После создания экземпляра класса с ним можно работать с помощью ряда методов:

t.Clear; // очищаем класс

t.LoadFromFile('имя файла'); // загружаем в класс файл для обработки

t.SaveToFile('имя файла'); // сохраняем в файл содержимое класса

t.Add('текст'); // добавляем в конец класса строку с текстом

t.Delete(i); // удаляем из класса строку с номером i (нумерация начинается с 0)

t.Free; // удаляет из памяти класс по завершению работы с ним

Проверка существования файла

Метод LoadFromFile () может не сработать, если указанного файла не окажется на диске. Перед его вызовом необходимо проверять наличие файла с помощью функции FileExists ( 'имя файла').

 

if FileExists('имя файла') then

файл существует

else

файл не существует

 

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

 

// опишем переменные

var t: TStringList; a, b: real;

begin

// если файл существует

if FileExists('primer.txt') then

begin

// задаем данные для добавления

a := 10;

b := 20;

// создаем экземпляр класса

t := TStringList.Create;

// загружаем файл в класс

t.LoadFromFile('primer.txt');

// добавляем в класс новые значения

t.Add(FloatToStr(a));

t.Add(FloatToStr(b));

// сохраняем содержание класса в файл

t.SaveToFile('primer.txt');

// удаляем из памяти класс

t.Free;

end;

end;

 

Пример. Пусть имеется два текстовых поля Edit1 и Edit2. Необходимо посчитать сумму этих полей и записать результат в файл с поясняющей текстом.

 

// опишем переменные (rez - для расчета суммы)

var t: TStringList; rez: real;

begin

// Считаем сумму

rez := StrToFloat(Edit1.Text) + StrToFloat(Edit2.Text);

// создаем экземпляр класса

t := TSringList.Create;

// очищаем класс

t.Clear;

// в классе формируем текст

t.Add('Исходные данные:');

t.Add('- первое число =' + Edit1.Text);

t.Add('- второе число =' + Edit2.Text);

t.Add('Сумма' + FloatToStr(rez));

// сохраняем содержание класса в файл

t.SaveToFile('rez.txt');

// удаляем из памяти класс

t.Free;

end;

 

Пример. Скопировать текстовый файл под другим именем

 

// опишем переменную

var t: TStringList;

begin

// если файл существует

if FileExists('primer.txt') then

begin

// создаем экземпляр класса

t := TSringList.Create;

// загружаем файл в класс

t.LoadFromFile('primer.txt');

// сохраняем содержание класса под другим именем

t.SaveToFile('copy.txt');

// удаляем из памяти класс

t.Free;

end;

end;

 

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

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

Пример. В текстовом файле все значения меньше 10, увеличить в два раза.

 

// описываем вспомогательные переменные

// i - счетчик цикла

var t: TStringList; i: integer;

begin

// если файл существует

if FileExists('primer.txt') then

begin

// создаем экземпляр класса

t := TSringList.Create;

// загружаем файл в класс

t.LoadFromFile('primer.txt');

// в цикле проходим по всем строкам класса

for i: = 0 to t.Count-1 do

// если в строке значение меньше 10

if StrToFloat(t.Strings[i])>10 then

// заменяем эту строку на значение, увеличенное в 2 раза

t.Strings[i]:=FloatToStr(StrToFloat(t.Strings[i])*2))

// сохраняем содержание класса в тот же файл (заменяем)

t.SaveToFile('primer.txt');

// удаляем из памяти созданный клас

t.Free;

end;

end;

 

Пример. В текстовом файле удалить строки, содержащие значение меньше 10.

 

// описываем вспомогательные переменные

// i - счетчик цикла

var t1, t2: TStringList; i: integer;

begin

// если файл существует

if FileExists('primer.txt') then

begin

// создаем экземпляр класса-источника

t1 := TSringList.Create;

// создаем экземпляр класса-приемника

t2 := TSringList.Create;

// загружаем файл в класс-источник

t1.LoadFromFile('primer.txt');

// очищаем класс-приемник

t2.Clear;

// в цикле проходим по всем строкам класса-источника

for i: = 0 to t1.Count-1 do

begin

// если в строке значение больше 10

if StrToFloat (t1.Strings[i])> 10 then

// записываем это число в класс-приемник

t2.Add(FloatToStr(c))

end;

// сохраняем содержание класса-приемника в тот же файл (заменяем)

t2.SaveToFile('primer.txt');

// удаляем из памяти созданы классы

t1.Free;

t2.Free;

end;

end;

 

Используя класс TStringList и знания языка разметки HTML можно проводит экспорт данных в формат WEB.

Пример. Пусть в поле Memo в 3 колонки отображаются числа, разделенные вертикальной линией. Необходимо экспортировать содержимое поля в файл HTML в виде таблицы.

 

procedure TForm1.Button1Click (Sender: TObject);

var t: TStringList;

  // счетчик цикла

  i: integer;

  // позиция для первой и второй вертикальных линий в строке

  p, p1: integer;

begin

  // создаем экземпляр класса в памяти

  t := TStringList.Create;

  // вставляет тег таблицы

  t.Add('<table width = "60%" border = "1px">');

  // создаем первую срока (шапку таблицы)

  t.Add('<tr>');

  t.Add('<td> первое число </ td>');

  t.Add('<td> второе число </ td>');

  t.Add('<td> сумма </ td>');

  t.Add('</ tr>');

 

  // в цикле проходим по всем срокам поля Memo

  for i: = 1 to Memo1.Lines.Count-1 do

  begin

     // находим позицию первой вертикальной линии

     p := pos('|', Memo1.Lines [i]);

     // создаем новую срока в таблице  

     t.Add('<tr>');

     // добавляем ячейку в первую колонку и пишем в нее первое число  

     t.Add('<td>' + copy (Memo1.Lines [i], 1, p-1) + '</ td>');

     // находим позицию второй вертикальной линии  

     p1 := pos('|', copy (Memo1.Lines [i], p + 1, length (Memo3.Lines [i]) - p));

     // добавляем ячейку во вторую колонку и пишем в нее второе число

     t.Add('<td>' + copy (Memo1.Lines [i], p + 1, p1-1) + '</ td>');

     // добавляем ячейку в третью колонку и пишем в нее третье число  

     t.Add('<td>' + copy (Memo1.Lines [i], p + p1 + 1, length (Memo3.Lines [i]) - p-p1) + '</ td>');

     // закрывает тег сроки

     t.Add('</ tr>');

  end;

  // закрываем тег таблицы

  t.Add('</ table>');

  // сохраняя полученное содержимое в файл HTML

  t.SaveToFile(ExtractFilEPath(Application.ExeName) + 'result.htm');

   // Удаляем экземпляр класса из памяти

  t.Free;

end;

 

6. Работа с папками и файлами с помощью функции WinAPI

Существует возможность работы с папками и файлами с помощью функций WinAPI. Данные функции встроены в саму операционную систему и могут вызываться в любом приложении на любом языке программирования.

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

·         при удалении файла или папки может показаться стандартный запрос на выполнение операции, а сама информация может помещаться в Корзину;

·         при копировании или перемещении больших порций данных на экране может отображаться окно с индикатором оставшегося времени и т.п.

Для использования таких функций в Delphi необходимо подключать модуль ShellAPI.

Рассмотрим функцию вида:

 

ShFileOperation (параметры)

 

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

К параметрам относятся:

·         wFunc - тип операции. Данный параметр может принимать значения FO_COPY - копирование, FO_MOVE - перемещение, FO_DELETE - удаление, FO_RENAME - переименование.

·         pFrom - указатель на строку с именем исходной папки или файла. Для задания требует соблюдения ряда правил (см. Пример ниже).

·         pTo - указатель на строку с именем результирующей папки или файла. Задается аналогично параметру pFrom.

·         fFlags - флажки, задающие параметры операции. Могут принимать значения: FOF_ALLOWUNDO - сохраняет информацию о возможной отмене операции; FOF_NOCONFIRMATION - отвечает "Да для всех" на все вопросы; FOF_SILENT - не показывают прогресс бар, отражающий ход операции; FOF_SIMPLEPROGRESS - отображает окно прогресс бара, но не показывает имен файлов; OF_NORECURSION - не отображает интерфейс при ошибке, FOF_NOCONFIRMMKDIR - не требует подтверждения создания нового каталога. Если нужно указать несколько флажков, то их объединяют операцией OR.

 

Пример. Удалить файл primer.txt с запросом и перемещением файла в корзину.

 

// переменная для задания параметров

var

p: TShFileOpStruct;

begin

// все параметры равны 0

ZeroMemory(@p, SizeOf(p));

// задаем нужные параметры

With p do

begin

// указываем тип операции

wFunc := fo_delete;

// указываем имя удаляемого файла

pFrom := PChar(ExtractFilePath(Application.ExeName) + 'primer.txt' + # 0);

// задаем флажок отмены операции (перемещение в корзину)

fFlags := fof_allowundo;

end;

// выполняем удаление

ShFileOperation(p);

end;

 

Несмотря на то, что файл primer.txt находится в одной папке с программой, в коде пришлось указать полный путь к файлу. Только в этом случае он будет помещен в Корзину. Если указать только имя файла или папки без пути, то объект удаляется без перемещения в Корзину, даже если указан флажок

 

fflags = fof_allowundo;

 

Если не нужно выдавать запрос на удаление файла и не нужно показывать индикатор удаления, то задайте флажок

 

fflag = fof_noconfirmation or fof_silent;

 

Для удаления папки вместо имени файла укажите имя папки. При этом удалить можно папку вместе со всем ее содержимым. Сделать это с помощью стандартных команд невозможно.

Операции копирования, перемещения и переименования выполняются аналогично, но дополнительно нужно указать параметр pTo, который задается аналогично параметру pFrom.

Например, скопировать файл файл primer.txt в папку d:\Files.

 

// переменная для задания параметров

var

p: TShFileOpStruct;

begin

// все параметры равны 0

ZeroMemory(@p, SizeOf(p));

// задаем нужные параметры

With p do

begin

// Указываем тип операции

wFunc := fo_copy;

// указываем имя копируемого файла

pFrom = PChar('primer.txt' + # 0)

// указываем папку для приема файла

pTo := PChar(d:\Files\'+ # 0)

// флажки по умолчанию

fFlags: = 0;

end;

// выполняем копирования

ShFileOperation(p);

end;

 

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

 

pFrom := PChar(ExtractFilePath(Application.ExeName) + 'primer.txt' + # 0)

 

то отмена будет возможна.

При выполнении приведенной выше операции выдается окно с индикатором копирования. Если в папке d:\files окажется одноименный файл, будет выдано окно с запросом на перезапись файла. Если мы хотим выполнить «скрытую» операцию копирования без сообщений и окон, то нужно включить флаги

 

fFlag := fof_noconfirmation or fof_silent;

 

Вопросы для самоконтроля

1. Опишите команды определения текущей папки, создания, перехода и удаления папки. Как проверить существование папки?

2. Приведите команды копирования, переименования и удаления файлов средствами команд Delphi. Как проверить существование файла?

3. Какие диалоги для работы с файлами вы знаете? Как вызвать такие диалоги? Какие свойства они имеют?

4. Как вызвать диалог выбора имени папки?

5. Как из полного имени файла извлечь части: диск, папку, имя файла и расширение? Как проверить существование папки? Как узнать полное имя файла программы?

6. Какой класс в Dephi позволяет выполнять операции над текстовыми файлами? Как создать экземпляр этого класса? Приведите свойства и методы этого класса.