Gå til innhold

C#: Recursive fil henting - trenger litt veiledning


Anbefalte innlegg

Hadde laget (startet på ;) ) en funksjon som søker gjennom et gitt mappe etter filer av typen x . Jeg har fått den til å finne alle filer i root mappa, og i alle mappe inni root mappa. Men hvordan burde jeg gå videre? Er litt tung i hopdet nå, så trenger litt hjelp for å komme meg videre.

 

using System;
using System.Collections;
namespace recurs
{
class recursive {


public System.Collections.ArrayList recursiveSearch(string startdir, string extension){
 
 ArrayList allFiles = new ArrayList();
 ArrayList folders = new ArrayList();
 ArrayList Filer = new ArrayList();
 
 foreach(string rFil in System.IO.Directory.GetFiles(startdir)){
 	allFiles.Add(rFil);
 }
 foreach(string rFolder in System.IO.Directory.GetDirectories(startdir)){
 	folders.Add(rFolder);
 }

 	foreach(string folder in folders){        	
   Console.WriteLine(folder);
   foreach(string fil in System.IO.Directory.GetFiles(folder)){	
   	allFiles.Add(fil);          
   }
 	}
 	foreach(string file in allFiles){
   if(System.IO.Path.GetExtension(file) == extension){
   	Filer.Add(file);
   }
 	}
 
 	return Filer;
 } // Funksjon slutt
  } // Klasse slutt
}

 

Si gjerne ifra om dumme ting jeg har gjort e.l :)

Lenke til kommentar
Videoannonse
Annonse

En av måtene å gjøre det på er:

public ArrayList recursiveSearch(string node, string extention)
{
   ArrayList files = new ArrayList();

   // Traverser alle kataloger og send de til rekursiv funksjon
   foreach (string folder in System.IO.Directory.GetDirectories(node))
       files.AddRange ( recursiveSearch(folder, extention) );

   // Traverser alle filer
   foreach (string file in System.IO.Directory.GetFiles(node))
       if (System.IO.Path.GetExtension(file) == extention)
           files.Add(file);

   return files;
}

Rekursive funksjoner kan være tung på stakken, så det finnes andre måter å gjøre det på. Uansett er ikke traversering av filtre noe problem her. Stakken vil ikke bli større enn dypeste nivå av noder.

Denne funksjonen returnerer ikke noe før den støter på første bladnode. Etter alle kataloger i hver "node" er gjennomgått vil filene i gjeldende katalog bli undersøkt.

 

Jeg anbefaler en investering i en bok om algoritmer og datastrukturer. Det er vel anvente penger! :thumbup:

 

Edit: Endret på parameternavn for klarhet.

Endret av TAFT
Lenke til kommentar

Løste problemet vet å sette opp to arraylister som køsystemer - den ene fylles opp med mappene fra root-mappa, kjører en foreach på den hvor alle mappene den finner inni de mappene som er i kø1 legger den til i kø2 og deretter cleares kø1, og kø2 eksekveres på samme måte.

Lenke til kommentar

Sikker på at du vil det? :p

 

Her er det i alle fall, husk at jeg er under opplæringsfasen ;)

 

Dette er en bit av klassen.

 

using System;
using System.Collections;

namespace RecursiveCsharp
{
/// <summary>
/// Summary description for recursive.
/// </summary>
public class recursive
{
 ArrayList allFiles = new ArrayList();
 ArrayList allFolders = new ArrayList();
 ArrayList folders = new ArrayList();
 ArrayList queue1 = new ArrayList();
 ArrayList queue2 = new ArrayList();
 bool X = true;
 

 public recursive()
 {
 }
 public System.Collections.ArrayList doRecursive(string root)
 {
 	foreach(string rFile in System.IO.Directory.GetFiles(root))
 	{
   allFiles.Add(rFile);
 	}
 	foreach(string rFolder in System.IO.Directory.GetDirectories(root))
 	{
   queue1.Add(rFolder);
   allFolders.Add(rFolder);
 	}
 	while(X)
 	{
   if(queue1.Count != 0)
   {
   	foreach(string q1 in queue1)
   	{
     foreach(string q1File in System.IO.Directory.GetFiles(q1))
     {
     	allFiles.Add(q1File);
     }
     foreach(string q1Folder in System.IO.Directory.GetDirectories(q1))
     {
     	queue2.Add(q1Folder);
     	allFolders.Add(q1Folder);
     }
   	}
 	
   	queue1.Clear();
 	
   	foreach(string q2 in queue2)
   	{
     foreach(string q2File in System.IO.Directory.GetFiles(q2))
     {
     	allFiles.Add(q2File);
     }
     foreach(string q2Folder in System.IO.Directory.GetDirectories(q2))
     {
     	queue1.Add(q2Folder);
     	allFolders.Add(q2Folder);
     }
   	}
   	queue2.Clear();
   }
   else 
   {
   	X = false;
   }
 	}
 	return allFiles;
 }

 public ArrayList getAllFolders()
 {
 	return allFolders;
 }

Lenke til kommentar

Har forsåvidt et lite problem emd den, den stopper hvis den prøver seg på en system amppe som den ikke har tilgang til, f.eks .\System Volume Information\ - Jeg har sett etter en funskjon som sjekker om jeg har tilgang til mappen, men finner bare for filer. Noen tips?

Lenke til kommentar

Algoritmen din er grei nok den. Den har en litt annen tilnærmingsmåte enn rekursiv traversering.

 

Når du (bl.a.) aksesserer filtreet kan det hende du ikke har tillatelser til alle filer. Når dette skjer oppstår det kan kaller et unntak (et tappert forsøk på fornorsking...) - eller en Exception, som det kalles. For at app'en din ikke skal tryne må du plassere denne koden i en try/catch-blokk. Slik som dette:

try
{
   foreach (string folder in Directory.GetDirectories(root))
   {
       // Gjør noe her...
   }
}
catch (Exception ex)
{
   Console.WriteLine("En feil oppsto: {0}", ex.Message)
}
finally
{
   // Denne blokka skjer uansett utfall!
   // Her kan du gjøre evt opprydding
}

Lenke til kommentar

Har sett litt på algoritmen din og laget en liten forbedring.

Den jobber med to køer, men alternerer mellom dem slik at du slipper å tømme begge i hver loop, dessuten er det færre foreach-looper.

Skriver ut resultatet til skjerm, så du får endre hvis du vil ha de i en egen ArrayList.

Eneste "problemet" med dette er at du får resultatet "hulter til bulter" og ikke i en logisk rekkefølge, men du kan jo selvsagt bare sortere resultatet til slutt. Uansett, den rekursive algoritma er hakket mer effektiv i dette tilfellet - men det spiller vel ingen rolle :)

 

public static void topDownSearch(string node, string extention)
{
   ArrayList []queue = new ArrayList[2];
   queue[0] = new ArrayList();
   queue[1] = new ArrayList();
   int actualQueue = 0;
   int otherQueue = (actualQueue + 1) % 2;

   // Populate first node in actualQueue
   queue[0].Add(node);

   // Loop while items in actualQueue
   while (queue[actualQueue].Count > 0)
   {
       // Traverse actualQueue for files
       foreach (string folder in queue[actualQueue])
       {
           try
           {
               // Traverse files in folder
               foreach (string file in System.IO.Directory.GetFiles(folder))
               {
                   try 
                   {
                       if (System.IO.Path.GetExtension(file) == extention) 
                       {
                           Console.WriteLine(file);
                       }
                   }
                   catch
                   {
                       // Be silent!
                   }
               }
           }
           catch
           {
               // Be silent
           }
       }

       // Foreach folder, add subfolders in otherQueue
       foreach (string inFolder in queue[actualQueue])
       {
           try
           {
               foreach (string folder in System.IO.Directory.GetDirectories(inFolder))
                   queue[otherQueue].Add(folder);
           }
           catch (Exception ex0)
           {
               Console.WriteLine("Problem: {0}", ex0.Message);
           }
       }

       // Clear actualQueue and switch to otherQueue
       queue[actualQueue].Clear();
       actualQueue = (actualQueue + 1) % 2;
       otherQueue = (otherQueue + 1) % 2;
   }
}

Endret av TAFT
Lenke til kommentar

Opprett en konto eller logg inn for å kommentere

Du må være et medlem for å kunne skrive en kommentar

Opprett konto

Det er enkelt å melde seg inn for å starte en ny konto!

Start en konto

Logg inn

Har du allerede en konto? Logg inn her.

Logg inn nå
×
×
  • Opprett ny...