Ir al contenido



Foto

[MULTILENGUAJE] Copiar múltiples archivos y carpetas.


  • Por favor identifícate para responder
1 respuesta en este tema

#1 escafandra

escafandra

    Advanced Member

  • Moderadores
  • PipPipPip
  • 3.917 mensajes
  • LocationMadrid - España

Escrito 03 septiembre 2010 - 06:03

La copia de carpetas puede hacerse de una forma recursiva como los ejemplos mostrados en este hilo o usando las Shell Functions de windows. Este truco se basa en este segundo sistema, conocido, pero a veces poco entendido.

La API de Windows permite realizar esta tarea con SHFileOperation. Vamos a usar esa función a la que le pasaremos una lista de archivos de origen y una carpeta de destino.

Según la ayuda MSDN esa lista debe pasarse como un conjunto de cadenas seguidas separadas por un caracter nulo y terminada en un doble nulo. La cadena de la ruta de destino sigue la misma regla, pero en esta ocasión será una sola cadena.

La lista de archivos y/o carpetas se le pasa como una lista tipo TStrings. La función crea la carpeta de destino y en ella copia los elementos fuente.

Veamos los ejemplos de código en C/C++ y en delphi:

Comenzamos con C/C++:


cpp
  1. #include <Shellapi.h>
  2.  
  3. // Crea una carpeta y las subcarpetas de una ruta dada
  4. void CreatePath(char* Path)
  5. {
  6.   int l = strlen(Path);
  7.   char* fin = Path;
  8.   do{
  9.     if(*fin && *fin != '\\') continue;
  10.     *fin = 0;
  11.     CreateDirectory(Path, 0);
  12.     if(l) *fin = '\\';
  13.   }while(*fin++ && l--);
  14. }
  15.  
  16. // Copia una lista de archivos y/o Carpetas en una carpeta destino dada
  17. int XCopy(HWND hWnd, TStrings *From, String To)
  18. {
  19.   if(!From || To=="") return -1;
  20.  
  21.   CreatePath(To.c_str());
  22.  
  23.   // uso un caracter \255 como paso intermedio luego lo sustituiré por nulos
  24.   String sFrom = StringReplace(From->Text, "\r\n", "\255", TReplaceFlags()<<rfReplaceAll) + "\255";
  25.   for(int i=1; i<=sFrom.Length(); i++) if(sFrom[i] == '\255') sFrom[i] = 0;
  26.   To.SetLength(To.Length()+1); To[To.Length()]='\0';
  27.  
  28.   SHFILEOPSTRUCT FS;
  29.   ZeroMemory(&FS, sizeof(SHFILEOPSTRUCT));
  30.   FS.hwnd = hWnd;
  31.   FS.wFunc = FO_COPY;
  32.   FS.pFrom = sFrom.c_str();
  33.   FS.pTo =  To.c_str();;
  34.   FS.fFlags = FOF_NOCONFIRMMKDIR | FOF_NOCONFIRMATION;
  35.   return SHFileOperation(&FS);
  36. }



Un ejemplo de uso:


cpp
  1.   TStrings *From = new TStringList;
  2.   From->Add("C:\\AEAT\\Renta2009\\.install4j"); // Carpeta fuente
  3.   From->Add("C:\\AEAT\\Renta2009\\CloudScape"); // Carpeta fuente
  4.   From->Add("C:\\AEAT\\Renta2009\\derby.log");  // Archivo fuente
  5.   XCopy(Handle, From, "F:\\Prueba\\Mio\\fin"); 
  6.   delete From;




Ahora voy a colocar el mismo código en delphi:


delphi
  1. uses ShellApi;
  2.  
  3. // Crea una carpeta y las subcarpetas de una ruta dada
  4. procedure CreatePath(Path: string);
  5. var
  6.   l, fin: integer;
  7. begin
  8.   l:= Length(Path);
  9.   fin:= 0;
  10.   repeat
  11.     if (Path[fin] = '\') or (l = 0) then
  12.     begin
  13.       if l>0 then Path[fin]:= #0;
  14.       CreateDirectory(PCHAR(Path), 0);
  15.       if l>0 then Path[fin]:= '\';
  16.     end;
  17.     inc(fin); dec(l);
  18.   until (l<0);
  19. end;
  20.  
  21.  
  22. // Copia una lista de archivos y/o Carpetas en una carpeta destino dada
  23. function XCopy(Handle: HWND; From: TStrings; Dest: String): integer;
  24. var
  25.   FS: SHFILEOPSTRUCT;
  26.   SFrom: string;
  27. begin
  28.   Result:= -1;
  29.   if(From.Count > 0) or (Dest <> '') then
  30.   begin
  31.     CreatePath(PCHAR(Dest));
  32.     SFrom:= StringReplace(From.Text, #13+#10, #0, [rfReplaceAll]);
  33.  
  34.     ZeroMemory(@FS, sizeof(SHFILEOPSTRUCT));
  35.     FS.wnd:= Handle;
  36.     FS.wFunc:= FO_COPY;
  37.     FS.pFrom:= PCHAR(SFrom + #0);
  38.     FS.pTo:=  PCHAR(Dest + #0);
  39.     FS.fFlags:= FOF_NOCONFIRMMKDIR or FOF_NOCONFIRMATION;
  40.  
  41.     Result:= SHFileOperation(FS);
  42.   end;
  43. end;



Y un ejemplo de uso:


delphi
  1. var
  2.   From: TStrings;
  3. begin
  4.   From:= TStringList.Create;
  5.   From.Add('C:\AEAT\Renta2009\.install4j'); // Carpeta fuente
  6.   From.Add('C:\AEAT\Renta2009\CloudScape'); // Carpeta fuente
  7.   From.Add('C:\AEAT\Renta2009\derby.log');  // Archivo fuente
  8.   XCopy(Handle, From, 'F:\Prueba\Mio\fin');
  9.   From.Free;
  10. end;



Espero que el código sea claro y os sea de utilidad.


Saludos.

Edito para reparar hipervínculo
  • 0

#2 esocrates

esocrates

    Advanced Member

  • Miembro Platino
  • PipPipPip
  • 102 mensajes
  • LocationArgentina

Escrito 03 septiembre 2010 - 06:32

Muchas gracias escafandra.
Realmente es de mucha utilidad
Un saludo
  • 0