SS}}

Delphi.int.ru — Портал программистов

Вход Регистрация | Забыли пароль?

События

Сегодня:
Вопросы0    Ответы0    Мини-форумы0


Последние:
Вопрос02.04, 13:45 / #6688
Ответ29.03, 23:32 / #6682
Новости30 апреля 2012


Сейчас онлайн:
На сайте — 18
На IRC-канале — 1

Ссылки

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

Автор: Ерёмин Андрей
Использованы материалы: dmitry9.nm.ru

В данной статье показаны некоторые методы копирования файлов. Существуют и готовые функции - CopyFile(), CopyFileEx(), но порой они неприменимы. Например, при использовании функции CopyFile() с большими файлами мы не имеем доступа к процессу копирования, т.е. программа на некоторое время просто "зависает". Из методов, приведённых ниже, только первый позволяет контроллировать процесс копирования - можно добавить прогресс-индикатор выполнения или отображать объём скопированных данных.

1. Копирование методом Pascal

type TCallBack=procedure (Position,Size: Longint); {Для индикации процесса копирования} procedure FastFileCopy(Const InfileName, OutFileName: String; CallBack: TCallBack); const BufSize = 3*4*4096; { 48Kbytes дает прекрасный результат } type PBuffer = ^TBuffer; TBuffer = array [1..BufSize] of Byte; var Size : integer; Buffer : PBuffer; infile, outfile : File; SizeDone,SizeFile: Longint; begin if (InFileName <> OutFileName) then begin buffer := Nil; AssignFile(infile, InFileName); System.Reset(infile, 1); try SizeFile := FileSize(infile); AssignFile(outfile, OutFileName); System.Rewrite(outfile, 1); try SizeDone := 0; New(Buffer); repeat BlockRead(infile, Buffer^, BufSize, Size); Inc(SizeDone, Size); CallBack(SizeDone, SizeFile); BlockWrite(outfile,Buffer^, Size) until Size < BufSize; FileSetDate(TFileRec(outfile).Handle, FileGetDate(TFileRec(infile).Handle)); finally if Buffer <> Nil then Dispose(Buffer); System.Close(outfile) end; finally System.Close(infile); end; end else Raise EInOutError.Create('File cannot be copied into itself'); end;

2. Копирование методом потока.

procedure FileCopy(Const SourceFileName, TargetFileName: String); var S,T: TFileStream; begin S := TFileStream.Create(sourcefilename, fmOpenRead); try T := TFileStream.Create(targetfilename, fmOpenWrite or fmCreate); try T.CopyFrom(S, S.Size); FileSetDate(T.Handle, FileGetDate(S.Handle)); finally T.Free; end; finally S.Free; end; end;

3. Копирование методом LZExpand

uses LZExpand; procedure CopyFile(FromFileName, ToFileName : string); var FromFile, ToFile: File; begin AssignFile(FromFile, FromFileName); AssignFile(ToFile, ToFileName); Reset(FromFile); try Rewrite(ToFile); try if LZCopy(TFileRec(FromFile).Handle, TFileRec(ToFile).Handle) < 0 then raise Exception.Create('Error using LZCopy') finally CloseFile(ToFile); end; finally CloseFile(FromFile); end; end;

4. Копирование методами Windows

uses ShellApi; function WindowsCopyFile(FromFile, ToDir : string) : boolean; var F : TShFileOpStruct; begin F.Wnd := 0; F.wFunc := FO_COPY; FromFile:=FromFile+#0; F.pFrom:=pchar(FromFile); ToDir:=ToDir+#0; F.pTo:=pchar(ToDir); F.fFlags := FOF_ALLOWUNDO or FOF_NOCONFIRMATION; Result:=ShFileOperation(F) = 0; end; // Пример копирования: procedure TForm1.Button1Click(Sender: TObject); begin if not WindowsCopyFile('C:\UTIL\ARJ.EXE', GetCurrentDir) then ShowMessage('Copy Failed'); end;

Мной были сделаны некоторые эксперименты с данными функциями. Во всех случаях копировался один и тот же файл объёмом 122 Мб. Конечно, говорить о правильности результатов можно с трудом, ведь жёсткий диск работает по-разному - иногда быстрее, а иногда медленее. Но в любом случае, результаты есть:

Метод Опыт 1 (сек.) Опыт 2 (сек.) Средняя скорость
1
3.355
3.515
3.435
2
4.467
4.286
4.377
3
3.545
3.395
3.470
4
3.696
5.478
4.587

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

Автор: Ерёмин А.А.

Статья добавлена: 16 февраля 2006

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

Рейтинг статьи: 5.00 Голосов: 6 Ваша оценка:

Зарегистрируйтесь/авторизируйтесь,
чтобы оценивать статьи.


Статьи, похожие по тематике

 

Для вставки ссылки на данную статью на другом сайте используйте следующий HTML-код:

Ссылка для форумов (BBCode):

Быстрая вставка ссылки на статью в сообщениях на сайте:
{{a:19}} (буква a — латинская) — только адрес статьи (URL);
{{статья:19}} — полноценная HTML-ссылка на статью (текст ссылки — название статьи).

Поделитесь ссылкой в социальных сетях:


Комментарии читателей к данной статье

Ерёмин А.А.
Репутация: +40

Ерёмин А.А. (8 января 2012, 23:26):

Цитата (нескажу):

Подскажите плиз, как делать индикацию в 1 случае?

Взять размер файла с помощью FileSize(), ну а дальше понятно, надеюсь.
нескажу
Репутация: нет

нескажу (8 января 2012, 13:27):

Подскажите плиз, как делать индикацию в 1 случае?
Ерёмин А.А.
Репутация: +40

Ерёмин А.А. (26 апреля 2009, 23:21):

А в чём проблема? Не умеем циклы писать? :-)
demyan
Репутация: нет

demyan (26 апреля 2009, 17:43):

Отлично.
Еще бы про то как 10 файлов скопировать сразу а не один как на примере.

Оставлять комментарии к статьям могут только зарегистрированные пользователи.