Copiar un fichero

3336 vistas

Podemos usar la función ShFileOperation que permite, entre otras cosas, la copia de ficheros. En caso de error, el sistema mostrará un cuadro de diálogo indicando la causa del error. Los flags FOF_xxx configuran la operación (consultar la ayuda en linea para más información).



delphi
  1. function CopyFile(Source, Destination: String): boolean;
  2. var
  3.   fos: TSHFileOpStruct;
  4. begin
  5.   FillChar(fos, SizeOf(fos),0);
  6.   with fos do
  7.   begin
  8.     wFunc := FO_COPY;
  9.     pFrom := PChar(Source+#0);
  10.     pTo  := PChar(Destination+#0);
  11.     fFlags := FOF_ALLOWUNDO or FOF_NOCONFIRMATION or FOF_SILENT;
  12.   end;
  13.   result := (0 = ShFileOperation(fos));
  14. end;



Controlando los errores
No obstante, si queremos controlar los mensajes de error de la copia, tendremos que usar la función CopyFile(NombreFicheroInicial, NombreFicheroFinal: String; Control: boolean): boolean;
El parámetro "Control" indica cómo actuar en caso de que el fichero exista:
  • Si es true, no hará la copia y la función devolverá false
  • Si es false, reemplazará el fichero existente y la función devolverá true

Con barra de progreso
A veces, también puede ser interesante el mostrar una barra de progreso mientras se copia un fichero. Si usamos una función de alto nivel como CopyFile, nos simplificaremos mucho la vida, pero no podremos usar nuestra barra de progreso...
La solución que proponemos es la siguiente:

Paso 1: Abrir el fichero Origen y crear el Destino
Paso 2: Leer un bloque de datos del fichero Origen
Paso 3: Actualizar la barra de progreso
Paso 4: Grabar el bloque leido en el fichero Destino
Paso 5: Si no se ha copiado todo el fichero, volver al paso 2.

Un ejemplo:



delphi
  1. procedure TForm1.Button1Click(Sender: TObject);
  2. var
  3.   Origen,
  4.   Destino  :file of byte;
  5.   Buffer  :array[0..4096] of char;
  6.   Leidos  :integer;
  7.   Longitud :longint;
  8. begin
  9.   { Abrimos fichero Origen y Destino }
  10.   AssignFile(Origen,'c:\MiArchivoOrigen.txt');
  11.   reset(Origen);
  12.   AssignFile(Destino,'c:\MiArchivoDestino.txt');
  13.   rewrite(Destino);
  14.   { Hallamos la longitud del fichero a copiar }
  15.   Longitud := FileSize(Origen);
  16.   { Actualizamos limites de la ProgressBar }
  17.   ProgressBar1.Max := Longitud;
  18.   ProgressBar1.Min := 0;
  19.   while Longitud > 0 do
  20.   begin
  21.     BlockRead(Origen, Buffer[0], SizeOf(Buffer), Leidos);
  22.     Longitud := Longitud - Leidos;
  23.     BlockWrite(Destino, Buffer[0], Leidos);
  24.     ProgressBar1.Position := ProgressBar1.Position + Leidos;
  25.   end;
  26.   CloseFile(Origen);
  27.   CloseFile(Destino);
  28. end;



Este ejmplo usa un buffer de 2048 bytes. Cuando mayor sea el buffer, más velocidad daremos a la rutina.

Nota: se recomienda hacer controles estilo a mirar si el fichero existe, mirar si hay suficiente espacio en disco, comprobar si el destino existe y, en caso afirmativo preguntar qué hacer,....