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

Основная информация

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

BOOL CopyFile(
LPCTSTR lpExistingFileName, // pointer to name of an existing file
LPCTSTR lpNewFileName, // pointer to filename to copy to
BOOL bFailIfExists // flag for operation if file exists
);

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

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

Приведу небольшой пример использования этой функции. Создайте на диске C: файл ’1.txt’, а на форму поставьте кнопку:

procedure TForm1.Button1Click(Sender: TObject);
begin
  if CopyFile('c:1.txt','c:2.txt',true) then
    ShowMessage('Файл успешно скопирован!')
  else ShowMessage('Неудача!');
end; 

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

procedure TForm1.Button1Click(Sender: TObject);
begin
  if CopyFile('c:1.txt','c:2.txt',true) then
    ShowMessage('Файл успешно скопирован!')
  else
    ShowMessage('Ошибка! Вот ее код: '+IntToStr(GetLastError));
end;

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

function MyCopyFile( InFile,OutFile: String; From,Count: Longint ): Longint;
var
  InFS,OutFS: TFileStream;
begin
  InFS := TFileStream.Create( InFile, fmOpenRead );//создаем поток
  OutFS := TFileStream.Create( OutFile, fmCreate );//создаем поток
  InFS.Seek( From, soFromBeginning );//перемещаем указатель в From
  Result := OutFS.CopyFrom( InFS, Count );
  InFS.Free;//освобождаем
  OutFS.Free;//освобождаем
end;

Общие замечания

Перед копированием или удалением файлов всегда проверяйте его наличие функцией FileExists:

if FileExists('c:1.txt') then
  if CopyFile('c:1.txt','c:2.txt',true) then
    ShowMessage('Файл успешно скопирован!')

Чтобы использовать в функциях CopyFile и DeleteFile имена файлов полученные с помощью, например, OpenDialog, надо из привести к типу PChar:

if CopyFile(Pchar(OpenDialog1.FileName),Pchar(SaveDialog1.FileName),true) then
  ...

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

Копирование методом TurboPascal

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;

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

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;

Копирование методом 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;

Копирование методами 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;

Как скопировать все файлы вместе с подкаталогами

uses ShellApi;
procedure TForm1.Button1Click(Sender: TObject);
var
  OpStruc: TSHFileOpStruct;
  frombuf, tobuf: Array [0..128] of Char;
Begin
  FillChar( frombuf, Sizeof(frombuf), 0 );
  FillChar( tobuf, Sizeof(tobuf), 0 );
  StrPCopy( frombuf, 'h:\hook\*.*' );
  StrPCopy( tobuf, 'd:\temp\brief' );
  With OpStruc do
  begin
    Wnd:= Handle;
    wFunc:= FO_COPY;
    pFrom:= @frombuf;
    pTo:=@tobuf;
    fFlags:= FOF_NOCONFIRMATION or FOF_RENAMEONCOLLISION;
    fAnyOperationsAborted:= False;
    hNameMappings:= Nil;
    lpszProgressTitle:= Nil;
  end;
  ShFileOperation( OpStruc );
end;

Копирование группы файлов, используя диалог с анимацией «Копирование Файлов», который использует «Проводник»

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

TO_COPY 
FO_DELETE 
FO_MOVE 
FO_RENAME

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

uses ShellAPI;  
procedure TForm1.Button1Click(Sender: TObject); 
var
  Fo    : TSHFileOpStruct; 
  buffer: array[0..4096] of char; 
  p     : pchar; 
begin
  FillChar(Buffer, sizeof(Buffer), #0); 
  p := @buffer; 
  p := StrECopy(p, 'C:\DownLoad\1.ZIP') + 1; 
  p := StrECopy(p, 'C:\DownLoad\2.ZIP') + 1; 
  p := StrECopy(p, 'C:\DownLoad\3.ZIP') + 1; 
  StrECopy(p, 'C:\DownLoad\4.ZIP'); 
  
  FillChar(Fo, sizeof(Fo), #0); 
  Fo.Wnd    := Handle; 
  Fo.wFunc  := FO_COPY; 
  Fo.pFrom  := @Buffer; 
  Fo.pTo    := 'D:\'; 
  Fo.fFlags := 0; 
  if ((SHFileOperation(Fo) <> 0) or (Fo.fAnyOperationsAborted <> false)) then
    ShowMessage('Cancelled') 
end; 
1 Звезда2 Звезды3 Звезды4 Звезды5 Звезд (11 оценок, среднее: 5,00 из 5)
Загрузка...
Добавить комментарий