Delphi копирование папки с файлами

Обновлено: 07.07.2024

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

В самом простом случае вопрос копирования файлов очень прост (хотя поступило много пожеланий рассказать именно об этом)! Для этого достаточно посмотреть в хелп по Delphi :))

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

В Delphi есть функция CopyFile. Вот ее описание из хелпа

Параметры передаваемые в эту функцию:

  1. Указатель на имя существующего файла (нуль терминированная строка т.е. тип PChar! )
  2. Указатель на имя файла, который будет создан/перезаписан после копирования (нуль терминированная строка т.е. тип PChar! )
  3. Если этот параметр True и файл с таким именем уже существует, то функция вернет False. Если же файл, с именем указанным во втором параметре существует и в качестве третьего параметра передан False - то функция перезапишет файл и благополучно завершится.

Для того, чтобы точнее узнать при возникновении ошибки, что же все таки произошло, надо воспользоваться функцией GetLastError, которая возвращает код последней ошибки (формат DWORD). Теперь мы немного изменим пример:

Коды всех ошибок можно легко найти в хелпе.

Для углубления рассматриваемого вопроса приведу пример копирования файлов с помощью файлового потока (TFileStream). В приведенной пользовательской функции введены два дополнительных параметра From и Count, которые указывают, соответственно, с какого и по какой байт нужно копировать файл. Если необходимо скопировать весь файл, то необходимо передать нули. Вот код этой функции:

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

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

Удаление пустой директории

Чтобы удалить пустую директорию с помощью Delphi достаточно обратиться к функции RemoveDir.

Эта функция возвращает True если директория, указанная в единственном параметре, передаваемом в функцию, успешно удалена, в противном случае функция возвратит False.

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

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

Общие замечания по данной теме

  1. Перед копированием или удалением файлов всегда проверяйте его наличие функцией FileExists:
  2. Чтобы использовать в функциях CopyFile и DeleteFile имена файлов полученные с помощью, например, OpenDialog, надо из привести к типу PChar:
  3. Всегда следите за именами файлов, используемых в функциях. Обращайте внимание на абсолютные и относительные пути. Из-за этого часто возникают ошибки, которые сложно отследить!

Ну вот наверно и все, что я хотел бы рассказать Вам о копировании и удалении в Delphi.

Если вам помог материал сайта кликните по оплаченной рекламе размещенной в центре

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

Как известно, файлы имеют различные форматы и к ним применяются различные программы для обработки. Например, файлы рисунков BMP, текстовые файлы TXT и т.п. Файлы имеют различные имена и определенное расширение, имеющее в среде MS-DOS максимально три символа. Если у файла расширение RAR, то пользователь и операционная система знает, что это архиватор, причем windosw для обработки этого файла применяет средства, указанные в специальном разделе реестра.

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

Для копирования файлов применяется функция CopyFile. Формат ее такой:

CopyFile является функцией, которая возвращает флаг успешной или нет операции копирования.

Например, следующая строка:

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

Для перемещения файлов применяется функция MoveFile. Она имеет следующий формат:

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

Переименование файлов

У всех вышесказанных командах параметры исходного и конечного файла имеет тип PChar. Это строковый тип с завершающимся нулем. Возможно, вы раньше слышали о таком формате строковых данных. В такую переменную можно занести строку очень большой длины. Ее размер ограничивается наличием нулевого байта в конце. Теоретически такая переменная может иметь бесконечный размер. На практике она ограничивается размерами выделяемой памяти для программы (2Гб).

Преобразование обычной строковой переменной, типа String в PChar производится функцией:

При этом, для команд файловых операций возможны объединение строк. Например:

procedure TForm1.Button1Click(Sender: TObject);

Var InDir,OutDir:String; // объявление строковых переменных

InDir:='c:\1\'; // каталог исходных файлов

OutDir:='c:\2\'; // каталог записуемых файлов

Здесь налицо операция соединения двух строковых переменных.

В итоге этой процедуры будет копирование файлов c:\1\1.txt и c:\1\2.txt в каталог c:\2. Файлы копируются под теми же именами.

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

Работа с текстовыми файлами. Чтение из текстового файла

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

Все это благодаря свойству Lines, в котором хранятся строки.

Но на практике иногда необходимо прочитать только определенную строку или совершить операцию добавления строки в уже существующий файл.

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

Varf:TextFile; // объявление файловой переменной

st:String; // строковая переменная

AssignFile(f,'c:\1.txt'); // привязка названия файла к файловой переменной

// отключение контроля ошибок ввода-вывода

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

// включение контроля ошибок ввода-вывода

ifIOResult<>0 then // если есть ошибка открытия, то

ShowMessage('Ошибка открытия файла C:\1.TXT');

Exit; // выход из процедуры при ошибке открытия файла

While not EOF(f) do // пока не конец файла делать цикл:

ReadLn(f,st); // читать из файла строку

ShowMessage(st); // выводить строку пользователю

CloseFile(f); // закрыть файл

Прокомментирую некоторые строки этого примера.

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

и являются директивами компилятору, что в этом месту соответственно следует отключить и включить контроль ошибок ввода-вывода. В данном случае при неудачной попытке открытия файла c:\1.txt (файл отсутствует или открыт для записи другой программой) наша программа не выдаст аварийной ошибки и продолжит выполнение данной процедуры. Это свойство полезно для обработки всех возможных случаев в работе программы.

Работа с текстовыми файлами. Запись в текстовый файл

procedure TForm1.Button1Click(Sender: TObject);

Var f:TextFile; // указатель на текстовый файл

AssignFile(f,'c:\1.txt'); // привязка названия к переменной

Append(f); // открыть файл для добавления

if IOResult<>0 then // если ошибка открытия (напр. файла нет)

Rewrite(f); // создать новый файл

if IOResult<>0 then // ошибка создания файла

ShowMessage('Ошибка создания файла C:\1.TXT');

WriteLn(f,'Привет'); // запись в файл строки с символами перевода строки

CloseFile(f); // закрыть файл

Процедура Append(Файл) открывает файл для записи и устанавливает указатель записи в конец файла, т.е. все добавляемые к файлу строки будут записаны в конец файла.

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

Запись и чтение из файла не текстовых данных

Рассмотрим пример, в котором программа при выходе сохраняет свои размеры и положение окна на экране в файл и при последующем запуске восстанавливает состояние, которое было при выходе. Программа состоит из двух процедур OnShow и OnClose для окна Form1 программы.

procedure TForm1.FormShow(Sender: TObject);

Var f:file of Integer; // файловая переменная, тип integer

i:Integer; // целочистенная переменная

begin

if IOResult<>0 then Exit;

Read(f,i); //считать из файла значение

Form1.Top:=i; // верхнее положение окна

Form1.Left:=i; // левое положение окна

Form1.Width:=i; // ширина окна

Form1.Height:=i; // высота окна

end;

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);

Var f:file of Integer;

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

За копирование файлов в Delphi отвечает функция CopyFile, она имеет следующий синтаксис:
CopyFile(Начальный_файл, Конечный_файл, Перезапись);

Где,
Начальный_файл - Полный путь с указанием имени и расширения к файлу, который будет копироваться.
Конечный_файл - Полный путь с указанием имени и расширения куда копируем.
Перезапись – Если такой файл уже существует, то будет ли он перезаписан (true - не будет, false - будет).

Пример:

CopyFile('C:\1.txt', 'D:\1.txt', true);

Обратите внимание, что при указании второго параметра (Конечный_файл) мы указываем не просто папку куда хотим скопировать файл, но и еще желаемое имя с расширение файла. Т.е если Начальный файл c:\1.txt, то если указать имя конечного файла как d:\1Copy.txt то в процессе копирования наш 1.txt переименуется в 1Copy.txt.

За переименование файлов в Delphi отвечает функция RenameFileсинтаксис у неё очень простой и чем то схож с функцией копирования.

RenameFile('Начальное_имя','Конечное_имя')
Начальное_имя - Полный путь с указанием имени и расширения, к файлу, который будет переименован.
Конечное_имя - Полный путь к файлу с указанием нового имени и расширения.

Пример:

Что бы переместить файл, в Delphi используется функция MoveFile. Давайте посмотрим на её синтаксис:
MoveFile(Начальный_файл, Конечный_файл);

Где,
Начальный_файл - Полный путь с указанием имени и расширения к файлу, который будет перемещаться.
Конечный_файл - Полный путь с указанием имени и расширения куда перемещаем.

Здесь также следует обратить внимание на то что при указании второго параметра (Конечный_файл) мы указываем не просто папку куда хотим переместить файл, но и еще желаемое имя с расширение файла. Т.е если Начальный файл c:\1.txt, то если указать имя конечного файла как d:\1Paste.txt то в процессе перемещения наш 1.txt переименуется в 1Paste.txt.

Наверное, самая простая из рассмотренных выше функций это функция удаления, DeleteFile.

DeleteFile('Имя_файла');
Имя_файла - здесь предполагается указание полного пути, имени и расширения удаляемого файла.

Delphi site: daily Delphi-news, documentation, articles, review, interview, computer humor.

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

Эта функция возвращает true, если операция прошла успешно, и false, если неудачно.

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

Для удаления директорий есть отдельная функция:

Функция возвращает true, если операция прошла успешно, и false, если неудачно.

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

ChDir('Путь к папке, которая будет использоваться по умолчанию'); Это процедура, и у нее нет возвращаемого значения.

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

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

FileExists " 'Имя или полный путь к файлу');.

Если файл существует, то функция вернет true, иначе - false.

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

Если директория существует, то вернет true, иначе - false.

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

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

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


Source, Dest: Integer; Len: Integer; Destination: const

GetMem(CopyBuffer, ChunkSize) ; try

Source:»FileOpen(FileName, fmShareDenyWrite);//Открыть файл-источник if Source " 0 then raise EFOpenError.CreateFmt(SFOpenError, [FileName]); try

Dest := FileCreate(Destination); //Создать файл-приемник if Dest " 0 then raise try

//Считать порцию файла

BytesCopied'.=FiieRead(Source,CopyBufЕегЛ,ChunkSize); if BytesCopied " 0 then //Если порция считана, то. //Записать ее в файл-приемник FileWrite(Dest, Copy-Buffer", BytesCopied); until BytesCopied " ChunkSize; finally

Процесс копирования очень прост. Процедура получает два имени файла: откуда копировать, и куда. После этого происходит проверка. Если в качестве второго параметра (путь к файлу, в который надо скопировать)' указана только директория без имени файла, то программа подставляет в качестве имени файла имя источника.

После этого источника открывается для чтения данных с запретом на запись со стороны других программ. Открыв источник, процедура создает файл приемника. Если он существовал, то без каких-либо предупреждений файл будет перезаписан. Дальше запускается цикл, в котором из файла источника считываются данные по 8 192 байт и тут же записываются в файл приемника. Таким образом, в цикле происходит копирование файла небольшими порциями. Чем больше порция, тем быстрее будет происходить копирование.

Процедура копирования - очень хороший пример использования функций работы с файлами. Все сделано очень грамотно и великолепно работает, хотя и не очень универсально. Например, нет вызова предупреждения о существовании результирующего файла перед его уничтожением. Но это не так уж сложно сделатьС помощью функции F і 1 е Е х і s t s.

Теперь посмотрим на реализацию функции перемещения файлов (листинг 3.14). |1иС™нг^

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

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


Чтобы ее использовать, нужно добавить это описание в свой модуль. Только не забудьте добавить еще в раздел uses модуль shellAPi, иначе проект нельзя будет скомпилировать.

У функции четыре параметра.

П Имя ' файла, или полный путь к файлу, который надо запустить.

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

С помощью этой же функции можно запускать Internet Explorer (или другой браузер, который установлен по умолчанию) и загрузить Интернет-страничку:

Если нужно создать электронное письмо, то это можно сделать следующим способом:

Функцию ShellExecute мы уже рассматривали в разд. 2.5, и все же я решил описать ее еще раз, чтобы выделить в отдельную процедуру. Применяя ее, вам не надо следить за типом pchar, который используется- для передачи строк, потому что наша функция ExecuteFile сама сделает необходимые преобразования.

И сейчас мы перейдем к реальному примеру, который будем .изучать на практике. Создайте новый проект и перенесите на форму два компонента: ShellTreeView И ShellListView. У компонента ShellTreeView В СВОЙСТВе нужно указать компонент чтобы связать в одно целое. У компонента ShellListView нужно установить свойству Mutiselect значение true, чтобы мы могли выбирать несколько файлов.

Теперь нужно добавить панель, на которой мы разместим четыре кнопки: Копировать, Переместить, Удалить, Свойства. Мою форму будущей программы вы можете увидеть на рис. 3.17.

Форма будущей программы работы с несколькими файлами

Рис. 3.17. Форма будущей программы работы с несколькими файлами

Теперь перейдите в раздел uses и добавьте туда два модуля: shellapt. и FileCtrl. ПерВЫЙ МОДУЛЬ необходим ДЛЯ работы фуНКЦИИ SHFileOperation. Во ВЮрОМ есть фунКЦИЯ SelectDirectory, которая ВЫЮДИТ на экран стандартное окно выбора директории. Это окно мы будем использовать, когда нужно будет выбрать директорию, в которую надо скопировать или переместить файлы.

В разделе private добавим описание следующей функции:

private < Private declarations >function DoSHFileOp(Handle: THandle; OpMode: UInt; Src, Dest: string; DelRicleBin; Boolean): Boolean; Эта функция будет универсальная: для копирования, перемещения и удаления файлов. Нажмите "Ctrl"+"Shift"+"C", чтобы создать заготовку этой функции. В этой заготовке нужно написать следующее (листинг 3.16).

Листинг3.16. Универсальная функция для работы с файлами Г

function TForml.DoSHFileOp (Handle: THandle; CpMode: UInt; Src,.

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

- путь-источник, который мы получаем в качестве третьего параметра.

рто - путь-приемник, который мы получаем в качестве четвертого параметра.

• fof_simpleprogress - показать окно выполнения процесса, но не отображать имена файлов.

• IpszProgressTitle - текст, который будет отображаться в окне хода выполнения операции.

После раздела vaг и перед ключевым словом implementation напишите следующий код:

FileOpMode: array[0..3] of UInt =

Здесь мы объявили массив из четырех значений. Каждое из значений - это константа для обозначения определенной операции:

Теперь создадим обработчики событий для нажатия кнопок нашей панели. Сначала создайте обработчик события onclick для кнопки Копировать. В нем нужно написать следующий код (листинг 3.17).

for i := 0 to do if (ShellListViewl.items.item[i].Selected) then begin FSrc:=FSrc+

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

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

Окно выбора директории

Рис. 3.18. Окно выбора директории

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

for i := 0 to ShellListViewl.items.Count-1 do if (ShellListViewl. items, item[i] .Selected) then begin FSrc:=FSrc+

После этого вызывается написанная нами ранее процедура DoSHFiieOp, указывая все необходимые параметры. В качестве второго параметра указана операция, которую надо выполнить- FiieOpMode[0], что равно команде focopy. Третий и четвертый параметр - это пути источника и приемника (откуда и куда надо копировать).

Теперь напишем код для кнопки Переместить. Для этого в обработчике события onclick соответствующей кнопки пишем следующее (листинг 3.18).

for i := 0 to ShellListViewl.items.Count-1 do if (ShellListViewl.items.item[il.Selected) then begin FSrc:=FSrc+

Этот код идентичен тому, что мы написали для кнопки Копировать. Разница только в вызове процедуры DoSHFileOp, где мы указываем операцию FileOpMode [2], что означает перемещение. А в остальном там так же определяется директория, из которой нужно копировать, и так же формируется строка из имен файлов для копирования, разделенных нулевым символом.

В обработчике нажатия кнопки Удалить пишем следующий код (листинг 3.19).


for i := 0 to FilesListView.items.Count-1 do if then begin DelFName:=DelFName+

И снова код похож на тот, что мы уже использовали дважды. Но есть все-таки две разницы:

1. Мы проверяем, находится ли какой-нибудь файл в режиме редактирования ЕііезіЛз^іе*.І8Ес!Шп§. Если да, ТО ВЬМДМ ИЗ процедуры.

2. В вызове процедуры ОоЗНЕііеОр в качестве второго параметра мы напрямую указываем константу БорЕЬЕТЕ, хотя можно было бы указать РііеОрМоає [ 1], что абсолютно то же самое.

В обработчике нажатия кнопки Свойства напишем следующий код (листинг 3.20).

Здесь мало строчек кода, но с ним придется разбираться. В начале происходит простая проверка на выделение. Если пользователь ничего не выбрал, то выходим, иначе в следующей строке произойдет ошибка. Дальше мы вызываем функцию SHObjectProperties, которая отображает стандартное окно свойств объекта. У этой функции 4 параметра.

О Указатель на окно-владельца.

О Последний параметр оставляем равным nil.

На рис. 3.19 вы можете увидеть стандартное окно свойств, вызванное из нашей программы.

Стандартное окно свойств объекта

Рис. 3.19. Стандартное окно свойств объекта

Чтобы проект теперь скомпилировался, нужно сообщить о существовании функции зногое^Ргорегг^ез, о которой Ш1рЫ еще не знает. Для этого создайте файл stan.dardDialogs.pas и напишите в нем следующее (листинг 3.21).


windows, Messages, SHlObj,-

//Cancel the operation and close the dialog.

TSHObjectProperties = function(hwndOwner: HWND); uFlags:

Теперь добавьте в раздел uses имя нашего модуля standardDialogs и скомпилируйте проект. Теперь можете запустить проект и посмотреть результат.

На компакт-диске в директории \Примеры\Глава 3\File Operation вы можете увидеть пример данной программы и цветные версии рисунков.

Читайте также: