views:

286

answers:

6

I need to calculate the size of hundreds of folders, some will be 10MB some maybe 10GB, I need a super fast way of getting the size of each folder using C#.

My end result will hopefully be:

Folder1 10.5GB

Folder2 230MB

Folder3 1.2GB

...

+2  A: 

There is no simple way to do this in .Net; you will have to loop through every file and subdir. See the examples here to see how it's done.

Jouke van der Maas
It seems slow in Windows too so maybe there isn't a fast method, calculating the size for 100s or 1000s of large folders may not be feasible then :-(
LeeW
After reading all the comments I've decided against doing this, is was to be a nice to have feature but the overhead is to great. Thanks all.
LeeW
+1  A: 

You can do something like this, but there's no fast=true setting when it comes to getting folder sizes, you have to add up the file sizes.

    private static IDictionary<string, long> folderSizes;

    public static long GetDirectorySize(string dirName)
    {
        // use memoization to keep from doing unnecessary work
        if (folderSizes.ContainsKey(dirName))
        {
            return folderSizes[dirName];
        }

        string[] a = Directory.GetFiles(dirName, "*.*");

        long b = 0;
        foreach (string name in a)
        {
            FileInfo info = new FileInfo(name);
            b += info.Length;
        }

        // recurse on all the directories in current directory
        foreach (string d in Directory.GetDirectories(dirName))
        {
            b += GetDirectorySize(d);
        }

        folderSizes[dirName] = b;
        return b;
    }

    static void Main(string[] args)
    {
        folderSizes = new Dictionary<string, long>();
        GetDirectorySize(@"c:\StartingFolder");
        foreach (string key in folderSizes.Keys)
        {
            Console.WriteLine("dirName = " + key + " dirSize = " + folderSizes[key]);
        }

        // now folderSizes will contain a key for each directory (starting
        // at c:\StartingFolder and including all subdirectories), and
        // the dictionary value will be the folder size
    }
dcp
Where is the initial call to GetDirectorySize()? Without this, the code does nothing as folderSizes is empty.
JBRWilkinson
Also, folderSizes will also contain all subdirectories whereas it seems the OP just wants the sizes of the top level.
JBRWilkinson
@JBRWilkinson - Yep, in one of my edits I accidentally took out that initial call. Thanks for pointing it out. The dictionary will contain all the results, but the OP can use the ones he/she needs.
dcp
+2  A: 

OK, this is terrible, but...

Use a dos command:

DIR /S/-C > tempfile

Read the last 2 lines of the tempfile.

Repeat for each folder.

I don't think there are any command line options to return just the last few lines of the file. But, this is the data you're looking for. It will do thousands of files fairly quickly.

Good luck.

BoltBait
No, it's awesome and worthy, given the alternative...
Data Monk
A: 

There are some leads in this link (though it's in Python) from a person running into similar performance issues. You can try calling down into Win32 API to see if performance improves, but at the end you're going to run into the same issue: a task can only be done so quickly and if you have to do the task a lot of times, it will take a lot of time. Can you give more detail on what you're doing this for? It might help folks come up with a heuristic or some cheats to help you. If you're doing this calculation a lot, are you caching the results?

Tom
A: 

If you right click a large directory then properties you can see that it takes significant amount of time to calculate the size... I don't think we can beat MS in this. One thing you could do is index the sizes of directories/subdirs, if you are going to calculate them over and over again... that would significantly increase the speed.

You could use something like this to calculate directory size in C# recursively

static long DirSize(DirectoryInfo directory)
{
    long size = 0;

    FileInfo[] files = directory.GetFiles();
    foreach (FileInfo file in files)
    {
        size += file.Length;
    }

    DirectoryInfo[] dirs = directory.GetDirectories();

    foreach (DirectoryInfo dir in dirs)
    {
        size += DirSize(dir);
    }

    return size;
}
m0s
A: 

Dot Net Pearls has a method similar to the ones described here. It's surprising that the System.IO.DirectoryInfo class doesn't have a method to do this since it seems like a common need and it probably would be faster to do it without doing a native/managed transition on each file system object. I do think that if speed is the key thing, writing a non-managed object to do this calculation and then call it once per directory from managed code.

Mike Kelly