How do I get a human-readable file size in bytes abbreviation using .NET?

using Log to solve the problem....

static String BytesToString(long byteCount)
{
    string[] suf = { "B", "KB", "MB", "GB", "TB", "PB", "EB" }; //Longs run out around EB
    if (byteCount == 0)
        return "0" + suf[0];
    long bytes = Math.Abs(byteCount);
    int place = Convert.ToInt32(Math.Floor(Math.Log(bytes, 1024)));
    double num = Math.Round(bytes / Math.Pow(1024, place), 1);
    return (Math.Sign(byteCount) * num).ToString() + suf[place];
}

Also in C#, but should be a snap to convert. Also I rounded to 1 decimal place for readability.

Basically determine the number of decimal places in Base 1024 and then divide by 1024^decimalplaces.

And some samples of use and output:

Console.WriteLine(BytesToString(9223372036854775807));  //Results in 8EB
Console.WriteLine(BytesToString(0));                    //Results in 0B
Console.WriteLine(BytesToString(1024));                 //Results in 1KB
Console.WriteLine(BytesToString(2000000));              //Results in 1.9MB
Console.WriteLine(BytesToString(-9023372036854775807)); //Results in -7.8EB

Edit:
Was pointed out that I missed a Math.Floor, so I incorporated it. (Convert.ToInt32 uses rounding, not truncating and that's why Floor is necessary.) Thanks for the catch.

Edit2:
There were a couple of comments about negative sizes and 0 byte sizes, so I updated to handle those cases.


This may not the most efficient or optimized way to do it, but it's easier to read if you are not familiar with log maths, and should be fast enough for most scenarios.

string[] sizes = { "B", "KB", "MB", "GB", "TB" };
double len = new FileInfo(filename).Length;
int order = 0;
while (len >= 1024 && order < sizes.Length - 1) {
    order++;
    len = len/1024;
}

// Adjust the format string to your preferences. For example "{0:0.#}{1}" would
// show a single decimal place, and no space.
string result = String.Format("{0:0.##} {1}", len, sizes[order]);

Tags:

C#

.Net

Vb.Net