Kopiowanie plików

Adam Boduch

W tym artykule po krótce zostaną wyjaśnione sposoby na skopiowanie plików w języku Delphi, jak i również sposób na utworzenie oraz usunięcie katalogu.

Zacznijmy od kopiowania. Najprościej to zrobić za pomocą funkcji CopyFile. Kopiuje ona pojedynczy plik.

CopyFile('C:\main.exe', 'D:\main.exe', False);

Pierwszy parametr określa źródło kopiowania, drugi cel.
Ostatni parametr określa jak program ma się zachować jeżeli plik o takiej nazwie już istnieje: True - nie robić nic; False - podmienić.

Takie zastosowanie ma jednak wadę - nie można kopiować całego katalogu.
W takim wypadku można skorzystać z modułu ShellApi. Dodaj to słowo do listy Uses. Teraz możesz już korzystać z funkcji TSHFileOpStruct. Oto przykład kopiowania pliku:

var
  R : TSHFileOpStruct;
begin
 with R do
 begin
   Wnd:=Handle; // oznaczenie uchwytu
   lpszProgressTitle := 'Skopiuj plik....';// tutuł okienka
   wFunc:=FO_COPY;// opcja
   pFrom:='c:\system.zip'; // z pliku
   pTo:='c:\Windows\Pulpit\system.zip';// do pliku
   fFlags:=FOF_NOCONFIRMMKDIR;
 end;
SHFileOperation(R);

W ten sposób wywołane zostanie okienko, które kopiować będzie dany plik. Ta funkcja może też wykonywać inne operację. Wystarczy, że zmienisz parametr wFunc oznaczający opcję. Może to być także:

FO_RENAME - zmienia nazwę pliku lub katalogu z "wFrom" do "pTo".
FO_DELETE - kasuje nazwę katalogu. Parametr "wTo" zostaje ignorowany.
FO_MOVE - przenosi nazwę katalogu lub pliku z "wFrom" do "wTo".

Jeżeli chcesz skasować katalog lub plik, możesz użyć następujących funkcji:

Jeżeli chcesz natomiast utworzyć nowy katalog, należy skorzystać z takiego kodu:

MkDir('C:\katalog');

lub

CreateDirectory('C:\katalog', nil);

Drugim parametrem tej funkcji jest atrybut. Na razie możemy pozostawić go jako pusty (Nil).

Istnieje jeszcze problem usuwania katalogu. Jeżeli nie jest on pusty do usuwanie się nie powiedzie. Można temu zapowiedz pisząc własną funkcję, której nagłówek może wyglądać w ten sposób;

function DeleteDirectory( const dir, path : String) : Boolean;

Cialo funkcji:

var
  SR : TSearchRec;
  Found : Integer;
  source : String;
begin
 source := dir + path;

  Found := FindFirst( source+'\*.*', faAnyFile, SR );
    try
      while  (Found = 0)  do
        begin
          if (SR.Name<>'.') and (SR.Name <> '..') then
          begin
           if (SR.Attr and faDirectory) <> 0 then
           begin
             DeleteDirectory( dir, path+'\'+SR.Name );
           end
          else
          begin
           FileSetAttr(
           source+'\'+SR.Name, FileGetAttr(source+'\'+SR.Name) 
                 and
           not (faReadOnly or faHidden) );
            if not DeleteFile( source+'\'+SR.Name ) then
              Result := False;
            end;
         end;
          Found := FindNext( SR );
        end;
    finally
      FindClose(SR);
    end;
    RemoveDir( source );
end;

Teraz jeżeli chcesz usunąć katalog, wystarczy wywołać naszą funkcję:

DeleteDirectory('C:\', 'Perl');

9 komentarzy

Btw. Dlaczego w przykładzie usuwasz katalog Perla ? Przecież to grzech ;)

DeleteDirectory('C:\', 'Perl');

Oznacza to, że do proecedury zostanie użyta ścieżka C:\Perl\. Może to spowodować błąd*. Ja sam użyłem C:\Perl\ i dopiero zadziałało.

*nie kompilatora, ale w działniu i nie taki, że zostanie wyświetlony komunikat, ale że procedura nie usunie plików lub podfolderów.

Ale ogólnie to dobry <ort>artykół</ort>. Dzięki sposobowi na usuwanie plików - po małych modyfikacjach - zrobiłem procedure która zczytuje nazwy plików z podanego folderu do ListBox :-)

Wszystko ok ale u mnie nadpisuje plik przy ustawieniu trzeciego parametru na 'false'. Jakoś dziwnie ?

Miałem problem z kopiowaniem, obydwiema metodami. Nie znajdywał pliku. Rozwiązanie to lowercase(zmienna_z_nazwa_pliku). Mimo że Windows nie rozpoznaje wielkości znaków w nazwach plików, tak się dzieje. Nie wiem czemu.

nie on tak nie wchodzi...nie czaji co to jest fo_rename czyli pisze uncleared undefinier (coś ttakiego)

No czyli zapodaj koda jak to wytegować znaczy się zmienić nazwę pliku bo trochę nie skapowałem...tak to ma być: FO_RENAME('ścieżka pliku którego ma zmienić nazwę','nazwa pliku'); a jak nie tak to jak???

"Takie zastosowanie ma jednak wadę - nie można kopiować pliku."

Chyba chciales napisac folderu

Świetny artykuł! Dzięki niemu wreszcie mogę skopiować jakiś folder :-) Dla początkujących (kiedyś sam się z tym trudziłem) mówię, że jeśli się podaje jakiegoś stringa do PFrom lub do PTo, trzeba dać go w pchar, np. pFrom:=pchar(ExtractFileDir(Application.ExeName) + '\Files\PhpGuestBook\ksiegagosci');. Tak, wiem, proste jak drut, ale parę lat temu nie wiedziałem, że trzeba zrobić TO :-)