Introduction
DirectorySizer is a simple ASP.NET page programmed in C# that allows you to quickly and easily find the largest subfolders from a collection. This is a demo that covers different topics such as: Generics, the collection class known as SortedDictionary
, an example of how to use enums, how to partially output data before it has been fully processed (giving the user feedback right away), and how to get data from the file system using .NET.
Background
This DirectorySizer application was born out of the need to find out which subfolders were the largest so that I could quickly delete them in order to free up space in the file system. I was attempting to clean up some old back ups of our site which had become far too bloated! Unfortunately, Windows does not have this feature built in, and using dir /s from the command prompt is far too messy and difficult to find the largest files easily.
Using the Code
I have broken down the code into several helper methods. What follows is an example. Please note: I did not handle exceptions, so if you do not have proper permissions on a folder, as mentioned below, it will throw an exception which will crash the program if not handled properly.
protected static long GetDirectorySize(string dir)
{
string[] dirs = System.IO.Directory.GetDirectories(dir);
long size = 0;
size += GetFileSize(dir);
foreach (string directory in dirs)
{
size += GetDirectorySize(directory);
}
return size;
}
Here is where I used a SortedDictionary
, because it inherently orders our data for us:
System.Collections.Generic.SortedDictionary<double, /> directorySizes =
new System.Collections.Generic.SortedDictionary<double, />();
Adding to the collection is very simple; all I have to do is assign it. Note that I am putting the folder size as the key and the value as the path (a twist on the traditional way of using this class).
foreach (DirectoryInfo subdir in dir.GetDirectories())
{
subdirSize = GetDirectorySize(subdir.FullName);
directorySizes[subdirSize] = subdir.FullName;
totalSize += subdirSize;
}
The last step is very easy; just loop through and display the output (it will be automatically sorted):
IDictionaryEnumerator ie = directorySizes.GetEnumerator();
string subDirpath;
double size;
Response.Write("table start");
while (ie.MoveNext())
{
subDirpath = (string)ie.Value;
size = (double)ie.Key;
Response.Write(string.Format("{0}, {1}", subDirpath,
Math.Round(size / bytes_in_a_megabyte,2)));
Response.Flush();
}
Response.Write("</ /></tr />
</tbody />
</table />
");
Points of Interest
You can use Response.Flush()
in order to partially output the page while you are creating it so the user gets immediate feedback.
Response.Write(string.Format("{0}{1}", subDirpath,
Math.Round(size / bytes_in_a_megabyte,2)));
Response.Flush();
History
I will keep a running update of any changes or improvements I've made here. Please note, the code has much more explanation in it as well as ideas for possible improvements, so go look there first. I will update this page with more explanation when I have a bit more time.