Processing Folders Iteratively

This article shows how to retrieve subdirectories of a Windows directory iteratively instead of recursively. Typically, recursion is used to retrieve hierarchically recursive data such as directories. Please see my article Retrieving Hierarchically Recursive Data Iteratively for a description of retrieving hierarchically recursive data iteratively.

The example for this article is a console program that retrieves the directories of the user's Internet Explorer Favorites but could easily be adapted for other directories. If you are like me, your favorites are organized into many folders. This example does not retrieve the actual favorites, they are individual files within the directories. Reading the files (favorites) would be an easy addition.

To retrieve the directories, a class called "Folder" is used with the following members:

Name Type Description
Name string Unqualified folder name
Parent Folder Recursive reference to a parent folder
Attributes FileAttributes  
CreationTime DateTime  
LastAccessTime DateTime  
LastWriteTime DateTime  
Children List<Folder> Subdirectories
Level int Hierarchical depth, used only for formatting output
GetFolder Stack<Folder> ToDo, string root Gets the subdirectories of the directory
Qualify string Creates an absolute path
Unqualify string Gets just the unqualified name of a directory
PutFolder(Stack<Folder> ToDo, StreamWriter sw) void Writes the folder to the text file and queues the children

Note that the Name is just the unqualified name and does not include the qualification.

The Internet Explorer Favorites are usually stored in the "C:\Users\{User}\Favorites" directory, so Name in the Folder object for the top folder to be processed is just "Favorites". We use the following to get the "C:\Users\{User}" portion:

Environment.GetFolderPath(Environment.SpecialFolder.UserProfile);

To begin the iteration, we first create a "Folder" object for the top folder, "Favorites ", and push it onto the stack. After pushing "Favorites" onto the stack, we begin the iteration that pops it off the stack and processes it. We process each object (folder) by retrieving its children and pushing each of them onto the stack of folders to do.

The sample program retrieves the folders into "Folder" objects then uses (shows) a separate loop to write them to a text file. Note that you will need to change the name of the file in the sample program.

The following is the Main method of the console program:
  1. string RootFolderName = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile);  
  2.   
  3. Folder TopFolder = new Folder();  
  4. TopFolder.Name = "Favorites";  
  5. ToDo.Push(TopFolder);  
  6. // Create a StreamWriter
  7. try {sw = new StreamWriter(OutFilename);}  
  8. catch (Exception ex)  
  9. {  
  10.     Console.WriteLine("Output file error: {0}", ex.Message);  
  11.     return;  
  12. }  
  13. // Get the folders  
  14. Console.WriteLine("\tGetting");  
  15. while (ToDo.Count > 0)  
  16. {  
  17.     (ToDo.Pop()).GetFolder(ToDo, RootFolderName);  
  18.     // The following will write something to the console  
  19.     // just so we know the program is working.  
  20.     Console.WriteLine("\tToDo.Count={0}", ToDo.Count);  
  21. }  
  22. // Put the folders. Start by creating the ToDo stack again.  
  23. Console.WriteLine("\tPutting");  
  24. ToDo.Push(TopFolder);  
  25. while (ToDo.Count > 0)  
  26. {  
  27.     (ToDo.Pop()).PutFolder(ToDo, sw);  
  28.     // The following will write something to the console  
  29.     // just so we know the program is working.  
  30.     Console.WriteLine("ToDo.Count={0}", ToDo.Count);  
  31. }  
  32. sw.Flush();  
 Where the "ToDo" stack is:
  1. static Stack<Folder> ToDo = new Stack<Folder>();  
The  following is the "GetFolder" method:
  1. internal void GetFolder(Stack<Folder> ToDo, string root)  
  2. {  
  3.     string Path = root + '\\' + Qualify();  
  4.     DirectoryInfo di = new DirectoryInfo(Path);  
  5.     Attributes = di.Attributes;  
  6.     CreationTime = di.CreationTime;  
  7.     LastAccessTime = di.LastAccessTime;  
  8.     LastWriteTime = di.LastWriteTime;  
  9.     List<string> dirs = new List<string>(Directory.EnumerateDirectories(Path));  
  10.     foreach (string fn in dirs)  
  11.     {  
  12.         Folder sf = new Folder();  
  13.         sf.Name = Folder.Unqualify(fn);  
  14.         sf.Parent = this;  
  15.         sf.Level = Level + 1;  
  16.         Children.Add(sf);  
  17.         ToDo.Push(sf);  
  18.     }  
  19. }  
The  following is the "PutFolder" method:
  1. internal void PutFolder(Stack<Folder> ToDo, StreamWriter sw)  
  2. {  
  3.     string tabs = new string('\t', Level);  
  4.     sw.WriteLine("{0}{1} {2} {3}", tabs, Name, CreationTime, LastAccessTime);  
  5.     // since the stack is LIFO, the objects will be popped off in  
  6.     // reverse order from what they are pushed, so we will push  
  7.     // in reverse order   
  8.     for (int i = Children.Count - 1; i >= 0; --i)  
  9.         ToDo.Push(Children[i]);  
  10. }  


Similar Articles