Partage
  • Partager sur Facebook
  • Partager sur Twitter

Problème avec une fonction (boucle récursive)

Class + foreach + boucle récursive

Sujet résolu
    24 mai 2015 à 16:45:51

    Bonjour,

    Je vais essayer d'être précis dans mon problème...

    J'ai passé quelques heures à élaborer une fonction qui va rechercher des fichiers dans un dossier ainsi que ses sous-dossiers. Le but de celle-ci est de renvoyer un tableau avec le résultat. Je souhaite faire apparaitre ce résultat dans un DataGrid View.

    Lorsque je met à jour le DataGrid View depuis la fonction, tous les fichiers sont bien listés dans celui-ci.
    Mais lorsque j'appelle la fonction à un autre endroit, je n'obtiens que le premier fichier trouvé !

    Je n'arrive pas à trouver la solution... Et j'espère obtenir de l'aide par ici ! :)

    D'autre part, j'utilise un tableau et je dois donc initialiser obligatoirement celui-ci... Si je trouve plus de fichier que déclaré dans le tableau, j'aurais un problème ! Existe-t-il un moyen avec une liste de faire exactement la même chose que j'ai fait avec le tableau ? :-°

    Mon fichier class qui matérialise chaque fichier trouvé

    		public class File
    		{
    			private string fileName;
    			private DirectoryInfo fileDirectory;
    			private decimal fileSize;
    			private string fileExtension;
    			private DateTime fileModified;
    			private DateTime fileCreated;
    			private DateTime fileLastAccess;
    			
    			public string FileName
    			{
    				get {return fileName;}
    				set {fileName = value;}
    			}
    			public DirectoryInfo FileDirectory
    			{
    				get {return fileDirectory;}
    				set {fileDirectory = value;}
    			}
    			public decimal FileSize
    			{
    				get {return fileSize;}
    				set {fileSize = value;}
    			}
    			public string FileExtension
    			{
    				get {return fileExtension;}
    				set {fileExtension = value;}
    			}
    			public DateTime FileModified
    			{
    				get{return fileModified;}
    				set{fileModified = value;}
    			}
    			public DateTime FileCreated
    			{
    				get{return fileCreated;}
    				set{fileCreated = value;}
    			}
    			public DateTime FileLastAccess
    			{
    				get{return fileLastAccess;}
    				set{fileLastAccess = value;}
    			}
    		}

    Voici ma fonction de recherche

    		public File[] testGetFiles(string fileDirectory, string fileName, string fileExtension, bool subDirectorySearch)
    		{
    			File[] fileLibrary = new File[100000]; // Le fait de spécifier 100000 me posera un problème...
    			int i = 0;
    
    			try 
    			{
    				DirectoryInfo topDir = new DirectoryInfo(fileDirectory);
    				foreach (var fi in topDir.GetFiles(fileName + fileExtension, SearchOption.TopDirectoryOnly))
    				{
    					fileLibrary[i] = new File();
    					fileLibrary[i].FileName = fi.Name;
    					fileLibrary[i].FileDirectory = fi.Directory;
    					fileLibrary[i].FileSize = fi.Length;
    					fileLibrary[i].FileExtension = fi.Extension;
    					fileLibrary[i].FileModified = fi.LastWriteTime;
    					fileLibrary[i].FileCreated = fi.CreationTime;
    					fileLibrary[i].FileLastAccess = fi.LastAccessTime;
    					dgvResultat.Rows.Add(fi.Name, fi.Directory, fi.Length/1024, "ko", fi.Extension, fi.LastWriteTime, fi.CreationTime, fi.LastAccessTime); // Fonctionne parfaitement et ajoute TOUT le résultat à mon DataGrid View
    					i++;
    				}
    				if (subDirectorySearch == true)
    				{
    					foreach (var directory in Directory.GetDirectories(fileDirectory))
    					{
    						testGetFiles(directory, fileName, fileExtension, subDirectorySearch);
    					}
    				}
    			} 
    			catch (UnauthorizedAccessException) { }
    			catch (Exception) { }
    
    		    return fileLibrary;
    		}

    Voici l'appel de ma fonction

    			try
    			{
    				foreach (File fi in testGetFiles(fileDirectory, fileName, fileExtension, subDirectorySearch))
    				{
    					MessageBox.Show(fi.FileName); // Affiche le nom du premier fichier trouvé et renvoi l'erreur : La référence d'objet n'est pas définie à une instance d'un objet (mon DataGrid View contient tout de même TOUT le résultat de la recherche)
    				}
    			}
    			catch (UnauthorizedAccessException) { }
    			catch (Exception ex) { MessageBox.Show(ex.Message); }

    En espérant avoir été suffisamment clair et espérant que vous pourrez m'aider ! :magicien:

    • Partager sur Facebook
    • Partager sur Twitter
      24 mai 2015 à 16:59:33

      Utilise List<File> au lieu de File[].
      • Partager sur Facebook
      • Partager sur Twitter
      MysteryDash / 100 MPM / Développeur Freelance C#.NET / osu! / PS4 Offline Remote Play
        24 mai 2015 à 17:12:13

        En utilisant :

        List<File> myList = new List<File>();

        Comment puis-je spécifier un équivalent au code ci-dessous ? En fait, je ne sais pas trop comment utiliser ma liste avec plusieurs champs...

        fileLibrary[i] = new File();
        fileLibrary[i].FileName = fi.Name;

        Sinon pas d'idée concernant le problème d'affichage du résultat ?

        • Partager sur Facebook
        • Partager sur Twitter
          24 mai 2015 à 17:35:09

          Lis la doc un petit peu...

          Tu as la fonction Add(File) pour ajouter un objet de type File (que tu initialises avant). Note pour ta classe File, le C# possède les propriétées automatiques, je vois pas pourquoi tu t'embêtes à faire trois lignes de code par variable quand les propriétées automatiques te permettent de faire ça en quelques caractères, exemple : public string nom { get; set; } fonctionne très bien.

          "Mais lorsque j'appelle la fonction à un autre endroit, je n'obtiens que le premier fichier trouvé !" -> Je comprends pas trop là ce que tu veux dire.

          Ensuite tu peux regarder ici, la seconde réponse, ça pourrait déjà raccourcir ton code : http://stackoverflow.com/questions/929276/how-to-recursively-list-all-the-files-in-a-directory-in-c

          Enfin, utilise le débugger sur ta dernière boucle foreach (celle avec les MessageBox) pour voir quel est le contenu de tes variables, si elles sont toutes nulles c'est normal que tu ais l'erreur, en fait, c'est plutot normal, à un moment la boucle foreach arrive sur tout les objets File qui n'ont pas été initialisés, donc du coup toutes leurs valeurs sont nulles, c'est pour ça que je t'ai conseillé d'utiliser List<T> qui t'épargnera ce problème.

          • Partager sur Facebook
          • Partager sur Twitter
          MysteryDash / 100 MPM / Développeur Freelance C#.NET / osu! / PS4 Offline Remote Play
            24 mai 2015 à 18:39:41

            J'ai donc modifié la fonction pour utiliser une liste (très pratique, merci du conseil !).

            		public List<File> testGetFiles(string fileDirectory, string fileName, string fileExtension, bool subDirectorySearch)
            		{
            			List<File> listFile = new List<File>();
            
            			try 
            			{
            				DirectoryInfo topDir = new DirectoryInfo(fileDirectory);
            				foreach (var fi in topDir.GetFiles(fileName + fileExtension, SearchOption.TopDirectoryOnly))
            				{
            					listFile.Add(new File() {FileName=fi.Name, FileDirectory=fi.Directory, FileSize=fi.Length, FileExtension=fi.Extension, FileModified=fi.LastWriteTime, FileCreated=fi.CreationTime,FileLastAccess=fi.LastAccessTime});
            					//dgvResultat.Rows.Add(fi.Name, fi.Directory, fi.Length/1024, "ko", fi.Extension, fi.LastWriteTime, fi.CreationTime, fi.LastAccessTime);
            				}
            				if (subDirectorySearch == true)
            				{
            					foreach (var directory in Directory.GetDirectories(fileDirectory))
            					{
            						testGetFiles(directory, fileName, fileExtension, subDirectorySearch);
            					}
            				}
            			} 
            			catch (UnauthorizedAccessException) { }
            			catch (Exception ex) { MessageBox.Show(ex.Message); }
            
            			return listFile;
            		}


            Mon problème, je pense, c'est la récursivité sur ma fonction.

            Ce que je veux dire, c'est qu'en appelant la fonction avec un foreach lors du clique d'un bouton sur la WinForm je n'obtiens que le résultat du TopDirectory mais pas celui des sous-dossiers.

            Hors, je voudrai  que la liste retournée contiennent tous les fichiers File trouvés afin de récupérer chaque élément de la liste et les ajouter à mon DataGrid View.

            Pour le moment j'actualise mon DataGrid View directement dans ma fonction, mais c'est pas top en soit.

            • Partager sur Facebook
            • Partager sur Twitter
              24 mai 2015 à 20:25:08

              C'est logique en fait, je vais te poser une question qui devrait te débloquer : tu le stockes où le retour de cette ligne : testGetFiles(directory, fileName, fileExtension, subDirectorySearch); ?
              • Partager sur Facebook
              • Partager sur Twitter
              MysteryDash / 100 MPM / Développeur Freelance C#.NET / osu! / PS4 Offline Remote Play
                24 mai 2015 à 20:38:46

                Exacte !

                J'ai fini par trouver en faisant ainsi :

                		public static List<File> GetSearchFile(string fileDirectory, string fileName, string fileExtension, bool subDirectorySearch)
                		{
                			List<File> listFile = new List<File>();
                		    SearchFile(listFile, fileDirectory, fileName, fileExtension, subDirectorySearch);
                		    return listFile;
                		}
                		private static void SearchFile(List<File> listFile, string fileDirectory, string fileName, string fileExtension, bool subDirectorySearch)
                		{
                			try 
                			{
                				DirectoryInfo topDir = new DirectoryInfo(fileDirectory);
                				foreach (var fi in topDir.GetFiles(fileName + fileExtension, SearchOption.TopDirectoryOnly))
                				{
                					listFile.Add(new File() {FileName=fi.Name, FileDirectory=fi.Directory, FileSize=fi.Length, FileExtension=fi.Extension, FileModified=fi.LastWriteTime, FileCreated=fi.CreationTime,FileLastAccess=fi.LastAccessTime});
                				}
                				if (subDirectorySearch == true)
                				{
                					foreach (var directory in Directory.GetDirectories(fileDirectory))
                					{
                						SearchFile(listFile, directory, fileName, fileExtension, subDirectorySearch);
                					}
                				}
                			} 
                			catch (UnauthorizedAccessException) { }
                			catch (Exception ex) { MessageBox.Show(ex.Message); }
                		}


                Ensuite, il n'y a plus qu'à appeler...

                foreach (File fi in GetSearchFile(fileDirectory, fileName, fileExtension, subDirectorySearch)) {}

                Merci pour les conseils MysteryDash ! Outre me débloquer, cela m'a permis de mieux comprendre le C# et donc de pouvoir mieux chercher dans les docs à l'avenir ! :soleil:

                • Partager sur Facebook
                • Partager sur Twitter

                Problème avec une fonction (boucle récursive)

                × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
                × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
                • Editeur
                • Markdown