Vous ne trouvez pas de réponse à votre problème ? Alors posez la question dans le forum. Souvenez-vous qu'il n'y a jamais de question bête, mais rester dans l'ignorance parce que l'on n'ose pas poser une question, ça c'est une erreur !

Sujet : Copier tout le contenu d'un dossier avec barre de progression [ Divers / Débutant(e) ] (edge76000)

jeudi 14 décembre 2006 à 23:29:49 | Copier tout le contenu d'un dossier avec barre de progression

edge76000

Voici un exemple qui fonctionne. Seul bug : ça ne marche pas avec le lecteur D (cdrom) si quelqu'un sait pourquoi et comment corriger... Merci d'avance :-)
 

code



unit Principale;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, ComCtrls, FileCtrl;

type
  TF_Principale = class(TForm)
    Edt_Dossier_Source: TEdit;
    Btn_Parcourir_Source: TButton;
    Label1: TLabel;
    Memo_Log: TMemo;
    Label2: TLabel;
    Pgb_Fichier: TProgressBar;
    Pgb_Total: TProgressBar;
    Label3: TLabel;
    Label4: TLabel;
    Btn_Copier: TButton;
    Label5: TLabel;
    Edt_Dossier_Destination: TEdit;
    Btn_Parcourir_Destination: TButton;
    procedure Btn_Parcourir_SourceClick(Sender: TObject);
    procedure Btn_Parcourir_DestinationClick(Sender: TObject);
    procedure Btn_CopierClick(Sender: TObject);
  private
    { Déclarations privées }
  public
    { Déclarations publiques }

    // Fonctions de copies de fichiers
    procedure copierFichier( sFichierSource, sFichierDestination : string );
    procedure copierDossier( sDossierSource, sDossierDestination : string );
    function preparerCopie( sDossierSource : string ) : boolean;

  end;

var
  F_Principale: TF_Principale;
 
  giNbElements : integer;  // nombre d'éléments à copier

implementation

{$R *.dfm}

//
// Effectue la copie d'un fichier source vers sa destination.
//
// @param  string    sSource      Le chemin du fichier source à copier
// @param  string    sDestination  Le chemin destination où copier le fichier
//
procedure TF_Principale.copierFichier( sFichierSource, sFichierDestination : string );
var
  fichierSource, fichierDestination : file of byte;
  aBuffer : array[0..4096] of char;
  iPositionCourante : integer;
  iTailleFichier : longint;

begin

  // Ajout d'infos dans le log
  Memo_Log.Lines.Add('Copie de ' + sFichierSource + ' ... ');

  // Assignation du fichier source et ouverture
  AssignFile( fichierSource, sFichierSource );
  reset( fichierSource );

  // Assignation du fichier destination et création
  AssignFile( fichierDestination, sFichierDestination );
  Rewrite( fichierDestination );

  // Lecture taille fichier source pour la progressbar du fichier
  iTailleFichier := FileSize( fichierSource );

  // Initialisation progress bar
  Pgb_Fichier.Min := 0;
  Pgb_Fichier.Max := iTailleFichier;

  // Boucle sur le fichier pour faire la copie
  while iTailleFichier > 0 do
    begin
      // Lecture bloc d'octets de la taille du buffer (soit lecture par tranches de 4Ko dans notre cas)
      BlockRead( fichierSource, aBuffer[0], SizeOf(aBuffer), iPositionCourante );

      // Copie du tampon lu dans le fichier destination
      BlockWrite( fichierDestination, aBuffer[0], iPositionCourante );

      // On retranche ce qui a été lu de la taille du fichier pour marquer l'avancement de la copie
      iTailleFichier := iTailleFichier - iPositionCourante;

      // On fait avancer la barre de progression
      Pgb_Fichier.Position := Pgb_Fichier.Position + iPositionCourante;
    end;

  // Copie terminée, on ferme les fichiers
  CloseFile( fichierSource );
  CloseFile( fichierDestination );

end;

//
// Effectue la copie du contenu d'un dossier vers sa destination.
//
// @param  string    sDossierSource        Chemin du dossier à copier
// @param  string    sDossierDestination  Chemin du dossier où copier le contenu du dossier source
//
procedure TF_Principale.copierDossier( sDossierSource, sDossierDestination : string );
var
  srParcours : TSearchRec;

begin

  // Ajout du slash à la fin des chemins
  sDossierSource := IncludeTrailingPathDelimiter(sDossierSource);
  sDossierDestination := IncludeTrailingPathDelimiter(sDossierDestination);

  // Parcours du dossier
  if FindFirst( sDossierSource + '*.*', faAnyFile, srParcours ) = 0 then
    begin

      repeat

        // Si c'est un dossier, on relance une copie de dossier
        // Ceci est de la récursivité = une procédure qui s'appelle elle-même
        if ((srParcours.Attr and faDirectory) <> 0) then
          begin
            if (srParcours.Name <> '.') and
                (srParcours.Name <> '..') then
              begin
                // Création du dossier dans le dossier destination
                CreateDir( sDossierDestination + srParcours.Name );

                // Copie du contenu du sous-dossier
                copierDossier( sDossierSource + srParcours.Name, sDossierDestination + srParcours.Name );
              end;
          end

        // Sinon c'est un fichier, on peut le copier
        else
          begin
            copierFichier( sDossierSource + srParcours.Name, sDossierDestination + srParcours.Name );
            Pgb_Total.Position := Pgb_Total.Position + 1;
          end;

      // Passage à l'élément suivant
      until FindNext(srParcours) <> 0;

    // Fermeture du handle du parcours
    FindClose(srParcours);

  end;
   
end;

//
// Prépare la copie.
//
// Cette méthode ne fait que compter le nombre d'éléments à copier pour pouvoir
// utiliser la barre de progression générale, mais on pourrait imaginer ajouter un
// contrôle sur la place disponible sur le support destination en calculant
// aussi le poids total des éléments à copier.
//
// @param  string    sDossierSource    Le dossier à copier.
// @return  boolean                    Vrai : on peut lancer la copie. Faux : Il y a un problème, on ne peut pas lancer la copie
//
function TF_Principale.preparerCopie( sDossierSource : string ) : boolean;
var
  srParcours : TSearchRec;
 
begin

  // Ajout du slash à la fin des chemins
  sDossierSource := IncludeTrailingPathDelimiter(sDossierSource);

  // Parcours du dossier
  if FindFirst( sDossierSource + '*.*', faAnyFile, srParcours ) = 0 then
    begin

      repeat

        // Si c'est un dossier, on rentre dans le dossier
        // Toujours pareil que copierDossier, cette fonction est récursive
        if ((srParcours.Attr and faDirectory) <> 0) then
          begin
            if (srParcours.Name <> '.') and (srParcours.Name <> '..') then
                preparerCopie( sDossierSource + srParcours.Name );
          end

        // Sinon c'est un fichier
        else giNbElements := giNbElements + 1;

      // Passage à l'élément suivant
      until FindNext(srParcours) <> 0;

    // Fermeture du handle du parcours
    FindClose(srParcours);

  end;

  // Initialisation de la barre de progression du total
  Pgb_Total.Min := 0;
  Pgb_Total.Max := giNbElements - 1;

  Result := True;

end;

//
// Parcourir pour le dossier source
//
procedure TF_Principale.Btn_Parcourir_SourceClick(Sender: TObject);
var
  sDossierSource : string;

begin
  if SelectDirectory('Sélectionnez le répertoire source :', '', sDossierSource) then
    Edt_Dossier_Source.Text := sDossierSource;
end;

//
// Parcourir pour le dossier destination
//
procedure TF_Principale.Btn_Parcourir_DestinationClick(Sender: TObject);
var
  sDossierDestination: string;

begin
  if SelectDirectory('Sélectionnez le répertoire destination :', '', sDossierDestination) then
    Edt_Dossier_Destination.Text := sDossierDestination;
end;

//
// Lancement de la copie
//
procedure TF_Principale.Btn_CopierClick(Sender: TObject);
begin

  // Initialisation du nombre d'éléments à copier !! à ne pas oublier, c'est une variable globale !
  giNbElements := 0;

  // Ajout info dans le log
  Memo_Log.Lines.Add( 'Préparation de la copie. Veuillez patienter...' );
  Memo_Log.Lines.Add('');

  // si la préparation est ok, on lance la copie
  if preparerCopie( Edt_Dossier_Source.Text ) then
    begin
      copierDossier( Edt_Dossier_Source.Text, Edt_Dossier_Destination.Text );

      Memo_Log.Lines.Add('');
      Memo_Log.Lines.Add('Copie terminée !');
    end
  else
    Memo_Log.Lines.Add('Impossible d''effectuer la copie.');

end;

end.

vendredi 15 décembre 2006 à 02:08:34 | Re : Copier tout le contenu d'un dossier avec barre de progression

cirec

Membre Club Administrateur CodeS-SourceS
Réponse acceptée !
Salut,

l'écriture est interdite sur le CD Rom il faut donc changer le FileMode Qui est à fmOpenReadWrite par défaut.
J'ai pas testé mais ça devrait fonctionner:



procedure TF_Principale.copierFichier( sFichierSource, sFichierDestination : string );
var
  fichierSource, fichierDestination : file of byte;
  aBuffer : array[0..4096] of char;
  iPositionCourante : integer;
  iTailleFichier : longint;
  OldMode  : Integer;
begin
  OldMode := FileMode;// on sauvegarde
  // Ajout d'infos dans le log
  Memo_Log.Lines.Add('Copie de ' + sFichierSource + ' ... ');

  // Assignation du fichier source et ouverture
  FileMode := fmOpenRead;// on change
  AssignFile( fichierSource, sFichierSource );
  reset( fichierSource );

  // Assignation du fichier destination et création
  AssignFile( fichierDestination, sFichierDestination );
  Rewrite( fichierDestination );

  // Lecture taille fichier source pour la progressbar du fichier
  iTailleFichier := FileSize( fichierSource );

  // Initialisation progress bar
  Pgb_Fichier.Min := 0;
  Pgb_Fichier.Max := iTailleFichier;

  // Boucle sur le fichier pour faire la copie
  while iTailleFichier > 0 do
    begin
      // Lecture bloc d'octets de la taille du buffer (soit lecture par tranches de 4Ko dans notre cas)
      BlockRead( fichierSource, aBuffer[0], SizeOf(aBuffer), iPositionCourante );

      // Copie du tampon lu dans le fichier destination
      BlockWrite( fichierDestination, aBuffer[0], iPositionCourante );

      // On retranche ce qui a été lu de la taille du fichier pour marquer l'avancement de la copie
      iTailleFichier := iTailleFichier - iPositionCourante;

      // On fait avancer la barre de progression
      Pgb_Fichier.Position := Pgb_Fichier.Position + iPositionCourante;
    end;

  // Copie terminée, on ferme les fichiers
  CloseFile( fichierSource );
  CloseFile( fichierDestination );
  FileMode := OldMode;// et on restitue
end;

Pour plus d'information sur FileMode voir l'aide de Delphi

Sinon je pense qu'il serait préferable d'utilise les Streams à la place de AssignFile


 
@+
Cirec


vendredi 15 décembre 2006 à 17:16:18 | Re : Copier tout le contenu d'un dossier avec barre de progression

florenth

Membre Club
Non, non non: pas de streams: utilises plutot la procédure CopyFileEx() de l'API windows.
En plus d'être rapide, elle offre la possibilité d'utiliser une méthode callback et d'arreter à tout moment la copie si l'utilisateur le souhaite 8et si le developpeur le permet bien sur).

Je ne saurais te conseiller que ce lien, très complet et bien expliqué: http://nono40.developpez.com/sources/source0030/ de nos amis nono40 et Delphiprog

samedi 16 décembre 2006 à 00:18:58 | Re : Copier tout le contenu d'un dossier avec barre de progression

edge76000

@ Cirec : MERCI BEAUCOUP!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ça marche super bien :-)

@ florenth : il est vrai que l'arrêt à tout moment de la copie par l'utilisateur serait pertinent surtout que mon utilisateur copie normalement 400MO pratiquement...mais il n'est pas possible de modifier/ajouter simplement mon code pour cela tout comme l'a fait très bien Cirec?



Cette discussion est classé dans : fichier, dossier, copie, srparcours, sdossiersource


Répondre à ce message

Sujets en rapport avec ce message

aide pour copie de fichier [ par Staphane ] Bonjour    <P cl Listage de Fichier! [ par MAsterC ] Salut....Bon j'essaye de faire un listage de fichier dans un dossier dans un TListBox mais je n'y arrive pas ! :(Alors voici mon exemples....On a un d Effacement de fichier ou dossier [ par ryadus ] SalutJe voudrais savoir comment on fait à l'aide d'un algoritme pour effacer un fichier ou un dossier et tous les fichiers le comptenant,je sais déjà Filtrer un dossier pour un type de fichier. [ par FurySpike ] Bonjour tout le monde, Je cherche à filter un dossier pour récupérer tous les fichier tu même type pour ensuite stocker leur nom dans un tableu pour Compression dossier Zlib [ par lupra ] Bonjour,Je voulais savoir si il est possible de compresser plusieur fichiers ou un dossier en un seul fichier zip avec la Zlib ou autre??j ai deja reg Copie StringGrid dans fichier TXT [ par ryadus ] Salut;Je voudrais savoir comment peut on faire pour copier un tableau (StringGrid) dans un fichier TXT, histoire de sauvgarder les données du tableau; Vérouiller l'accès à un fichier ou un dossier [ par valval ] Est-il possible de vérouiller l'accès à un fichier ou un dossier(un peu comme sous windows2000 prof ou XP) avec une application delphi? Si oui, propos Copie des fichiers d'un dossier dans un autre avec une progress bar [ par serial warez ] Salut tout le monde Voila j'aimerais faire un code qui copie tous les fichiers et les sous-dossiers d'un répertoire dans un autre répertoire avec une connaitre la date d'un fichier ou dossier sur un serveur ? [ par Jiihad ] ben comme au titre j uen application  et je veux connaitre la date surtous d'un dossier  dans un server  par exemple ici a c lien  http://www.al7bar-f Copie de fichier [ par Kal ] De kelle maniere puis je copier un fichier d'un repertoire a un autre parce ke j'ai chercher du cote des routines de gestion de fichier mais je trouve


Nos sponsors

Sondage...

CalendriCode

Novembre 2008
LMMJVSD
     12
3456789
10111213141516
17181920212223
24252627282930

Consulter la suite du CalendriCode

Téléchargements

Logiciels à télécharger sur le même thème :



Développement réalisé par Nicolas SOREL (Nix) avec l'aide de : Cyril DURAND et Emmanuel BAÏSE, Merci à Vincent pour ses précieux conseils
CodeS-SourceS.com© Toute reproduction même partielle est interdite sauf accord écrit du Webmaster
CodeS-SourceS.com© est une marque déposée tous droits réservés
Temps d'éxécution de la page : 0,655 sec

Google Coop CodeS-SourceS Google Coop CodeS-SourceS


Certaines images présentes sur le site (notament certains avatars) sont issues des collections IconShock, donc si vous souhaitez utiliser ces icons vous devez les acheter, ne les copiez pas et ne utilisez pas dans vos sites et applications sans les avoir commandé.