{ 1. }{
You need a TProgressBar on your form for this tip.
Fьr diesen Tip wird eine TProgressBar benцtigt.
}procedure TForm1.CopyFileWithProgressBar1(Source, Destination: string);
var
FromF, ToF: fileof byte;
Buffer: array[0..4096] of char;
NumRead: integer;
FileLength: longint;
begin
AssignFile(FromF, Source);
reset(FromF);
AssignFile(ToF, Destination);
rewrite(ToF);
FileLength := FileSize(FromF);
with Progressbar1 dobegin
Min := 0;
Max := FileLength;
while FileLength > 0 dobegin
BlockRead(FromF, Buffer[0], SizeOf(Buffer), NumRead);
FileLength := FileLength - NumRead;
BlockWrite(ToF, Buffer[0], NumRead);
Position := Position + NumRead;
end;
CloseFile(FromF);
CloseFile(ToF);
end;
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
CopyFileWithProgressBar1('c:\Windows\Welcome.exe', 'c:\temp\Welcome.exe');
end;
{ 2. }{***************************************}// To show the estimated time to copy a file: procedure TForm1.CopyFileWithProgressBar1(Source, Destination: string);
var
FromF, ToF: fileof byte;
Buffer: array[0..4096] of char;
NumRead: integer;
FileLength: longint;
t1, t2: DWORD;
maxi: integer;
begin
AssignFile(FromF, Source);
reset(FromF);
AssignFile(ToF, Destination);
rewrite(ToF);
FileLength := FileSize(FromF);
with Progressbar1 dobegin
Min := 0;
Max := FileLength;
t1 := TimeGetTime;
maxi := Max div 4096;
while FileLength > 0 dobegin
BlockRead(FromF, Buffer[0], SizeOf(Buffer), NumRead);
FileLength := FileLength - NumRead;
BlockWrite(ToF, Buffer[0], NumRead);
t2 := TimeGetTime;
Min := Min + 1;
// Show the time in Label1
label1.Caption := FormatFloat('0.00', ((t2 - t1) / min * maxi - t2 + t1) / 100);
Application.ProcessMessages;
Position := Position + NumRead;
end;
CloseFile(FromF);
CloseFile(ToF);
end;
end;
{ 3. }{***************************************}// To show the estimated time to copy a file, using a callback function: type
TCallBack = procedure(Position, Size: Longint); { export; }procedure FastFileCopy(const InFileName, OutFileName: string;
CallBack: TCallBack);
implementationprocedure FastFileCopyCallBack(Position, Size: Longint);
begin
Form1.ProgressBar1.Max := Size;
Form1.ProgressBar1.Position := Position;
end;
procedure FastFileCopy(const InFileName, OutFileName: string;
CallBack: TCallBack);
const
BufSize = 3 * 4 * 4096; { 48Kbytes gives me the best results }type
PBuffer = ^TBuffer;
TBuffer = array[1..BufSize] of Byte;
var
Size: DWORD;
Buffer: PBuffer;
infile, outfile: file;
SizeDone, SizeFile: LongInt;
beginif (InFileName <> OutFileName) thenbegin
buffer := nil;
Assign(infile, InFileName);
Reset(infile, 1);
try
SizeFile := FileSize(infile);
Assign(outfile, OutFileName);
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));
finallyif Buffer <> nilthen
Dispose(Buffer);
CloseFile(outfile)
end;
finally
CloseFile(infile);
end;
endelseraise EInOutError.Create('File cannot be copied onto itself')
end; {FastFileCopy}procedure TForm1.Button1Click(Sender: TObject);
begin
FastFileCopy('c:\daten.txt', 'c:\test\daten2.txt', @FastFileCopyCallBack);
end;
{ 4. }{***************************************}function CopyFileWithProgressBar2(TotalFileSize,
TotalBytesTransferred,
StreamSize,
StreamBytesTransferred: LARGE_INTEGER;
dwStreamNumber,
dwCallbackReason: DWORD;
hSourceFile,
hDestinationFile: THandle;
lpData: Pointer): DWORD; stdcall;
begin// just set size at the beginning if dwCallbackReason = CALLBACK_STREAM_SWITCH then
TProgressBar(lpData).Max := TotalFileSize.QuadPart;
TProgressBar(lpData).Position := TotalBytesTransferred.QuadPart;
Application.ProcessMessages;
Result := PROGRESS_CONTINUE;
end;
function TForm1.CopyWithProgress(sSource, sDest: string): Boolean;
begin// set this FCancelled to true, if you want to cancel the copy operation
FCancelled := False;
Result := CopyFileEx(PChar(sSource), PChar(sDest), @CopyFileWithProgressBar2,
ProgressBar1, @FCancelled, 0);
end;
end;
Переведенный текст:
Код, предоставленный ниже, написан на языке Delphi и демонстрирует четыре различных подхода к копированию файла с индикацией прогресса:
Подход 1: В этом методе используется простой контроллер TProgressBar на форме для отображения прогресса операции копирования файла. Он читает исходный файл по частям, записывает данные в файл назначения и обновляет progress bar соответствующим образом.
Подход 2: В этом подходе отображается ориентировочное время для завершения операции копирования. Код рассчитывает это время, измеряя время, необходимое для чтения и записи каждой части данных, и затем использует это значение для обновления метки.
Подход 3: В этом методе используется функция обратного вызова для отчета прогресса операции копирования файла. Он определяет тип функции обратного вызова TCallBack и вызывает ее из процедуры FastFileCopy, чтобы обновить progress bar на форме.
Подход 4: В этом подходе код предоставляет.custom реализацию функции CopyFileEx с использованием Windows API. Функция CopyFileWithProgressBar2 вызывается Windows в регулярных интервалах во время операции копирования, позволяя обновить progress bar на форме.
Некоторые улучшения и предложения для каждого подхода:
Подход 1:
Улучшите производительность, увеличивая размер частей (текущий размер - 4096 байт).
Добавьте обработку ошибок для операций чтения/записи файлов.
Рассмотрите использование асинхронного ввода-вывода для улучшения производительности.
Подход 2:
Улучшите точность расчета ориентировочного времени, учитывая фактический скорость передачи файла.
Обновляйте метку более часто, чтобы обеспечить более гладкую индикацию прогресса.
Рассмотрите отображение ориентировочного времени в более пользовательском формате.
Подход 3:
Упростите функцию обратного вызова FastFileCopyCallBack, удалив необходимость в расчете максимального размера и позиции progress bar.
Рассмотрите использование более эффективной алгоритма копирования файлов, такого как использование памяти-карты файлов или асинхронного ввода-вывода.
Подход 4:
Улучшите обработку ошибок для вызовов Windows API (например, GetLastError()).
Рассмотрите реализацию логики отмены операции копирования.
Обновляйте progress bar более часто, чтобы обеспечить более гладкую индикацию прогресса.
В целом, Подход 1 предлагает простой и прямой способ реализации копирования файлов с индикацией прогресса. Подход 4 предоставляет больше контроля над операцией копирования и позволяет настроить индикацию прогресса. Другие подходы предлагают дополнительные функции, такие как ориентировочное время или функциональность обратного вызова.
Копирование файла с индикатором процесса: создайте форму Delphi, добавьте компонент TProgressBar и вызовите процедуру CopyFileWithProgressBar для копирования файла.
Комментарии и вопросы
Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS
Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.