Does .NET provide an easy way convert bytes to KB, MB, GB, etc.?

C#.NetByteMegabyte

C# Problem Overview


Just wondering if .NET provides a clean way to do this:

int64 x = 1000000;
string y = null;
if (x / 1024 == 0) {
    y = x + " bytes";
}
else if (x / (1024 * 1024) == 0) {
    y = string.Format("{0:n1} KB", x / 1024f);
}

etc...

C# Solutions


Solution 1 - C#

Here is a fairly concise way to do this:

static readonly string[] SizeSuffixes = 
                   { "bytes", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB" };
static string SizeSuffix(Int64 value, int decimalPlaces = 1)
{
    if (decimalPlaces < 0) { throw new ArgumentOutOfRangeException("decimalPlaces"); }
    if (value < 0) { return "-" + SizeSuffix(-value, decimalPlaces); } 
    if (value == 0) { return string.Format("{0:n" + decimalPlaces + "} bytes", 0); }

    // mag is 0 for bytes, 1 for KB, 2, for MB, etc.
    int mag = (int)Math.Log(value, 1024);

    // 1L << (mag * 10) == 2 ^ (10 * mag) 
    // [i.e. the number of bytes in the unit corresponding to mag]
    decimal adjustedSize = (decimal)value / (1L << (mag * 10));

    // make adjustment when the value is large enough that
    // it would round up to 1000 or more
    if (Math.Round(adjustedSize, decimalPlaces) >= 1000)
    {
        mag += 1;
        adjustedSize /= 1024;
    }

    return string.Format("{0:n" + decimalPlaces + "} {1}", 
        adjustedSize, 
        SizeSuffixes[mag]);
}

And here's the original implementation I suggested, which may be marginally slower, but a bit easier to follow:

static readonly string[] SizeSuffixes = 
                  { "bytes", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB" };

static string SizeSuffix(Int64 value, int decimalPlaces = 1)
{
    if (value < 0) { return "-" + SizeSuffix(-value, decimalPlaces); } 

    int i = 0;
    decimal dValue = (decimal)value;
    while (Math.Round(dValue, decimalPlaces) >= 1000)
    {
        dValue /= 1024;
        i++;
    }

    return string.Format("{0:n" + decimalPlaces + "} {1}", dValue, SizeSuffixes[i]);
}

Console.WriteLine(SizeSuffix(100005000L));

One thing to bear in mind - in SI notation, "kilo" usually uses a lowercase k while all of the larger units use a capital letter. Windows uses KB, MB, GB, so I have used KB above, but you may consider kB instead.

Solution 2 - C#

Checkout the ByteSize library. It's the System.TimeSpan for bytes!

It handles the conversion and formatting for you.

var maxFileSize = ByteSize.FromKiloBytes(10);
maxFileSize.Bytes;
maxFileSize.MegaBytes;
maxFileSize.GigaBytes;

It also does string representation and parsing.

// ToString
ByteSize.FromKiloBytes(1024).ToString(); // 1 MB
ByteSize.FromGigabytes(.5).ToString();   // 512 MB
ByteSize.FromGigabytes(1024).ToString(); // 1 TB

// Parsing
ByteSize.Parse("5b");
ByteSize.Parse("1.55B");

Solution 3 - C#

I would solve it using Extension methods, Math.Pow function and Enums:

public static class MyExtension
{
    public enum SizeUnits
    {
        Byte, KB, MB, GB, TB, PB, EB, ZB, YB
    }

    public static string ToSize(this Int64 value, SizeUnits unit)
    {
        return (value / (double)Math.Pow(1024, (Int64)unit)).ToString("0.00");
    }
}

and use it like:

string h = x.ToSize(MyExtension.SizeUnits.KB);

Solution 4 - C#

Since everyone else is posting their methods, I figured I'd post the extension method I usually use for this:

EDIT: added int/long variants...and fixed a copypasta typo...

public static class Ext
{
	private const long OneKb = 1024;
	private const long OneMb = OneKb * 1024;
	private const long OneGb = OneMb * 1024;
	private const long OneTb = OneGb * 1024;
	
	public static string ToPrettySize(this int value, int decimalPlaces = 0)
	{
		return ((long)value).ToPrettySize(decimalPlaces);
	}
	
	public static string ToPrettySize(this long value, int decimalPlaces = 0)
	{
		var asTb = Math.Round((double)value / OneTb, decimalPlaces);
		var asGb = Math.Round((double)value / OneGb, decimalPlaces);
		var asMb = Math.Round((double)value / OneMb, decimalPlaces);
		var asKb = Math.Round((double)value / OneKb, decimalPlaces);
		string chosenValue = asTb > 1 ? string.Format("{0}Tb",asTb)
			: asGb > 1 ? string.Format("{0}Gb",asGb)
			: asMb > 1 ? string.Format("{0}Mb",asMb)
			: asKb > 1 ? string.Format("{0}Kb",asKb)
			: string.Format("{0}B", Math.Round((double)value, decimalPlaces));
		return chosenValue;
	}
}

Solution 5 - C#

I know this is old thread already. but maybe someone will look for solution. And here's what I use and the easiest way

public static string FormatFileSize(long bytes)
{
	var unit = 1024;
	if (bytes < unit) { return $"{bytes} B"; }

	var exp = (int)(Math.Log(bytes) / Math.Log(unit));
	return $"{bytes / Math.Pow(unit, exp):F2} {("KMGTPE")[exp - 1]}B";
}

Get folder size (for example usage)

public static long GetFolderSize(string path, string ext, bool AllDir)
{
	var option = AllDir ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly;
	return new DirectoryInfo(path).EnumerateFiles("*" + ext, option).Sum(file => file.Length);
}

EXAMPLE USAGE:

public static void TEST()
{
	string folder = @"C:\Users\User\Videos";

	var bytes = GetFolderSize(folder, "mp4", true); //or GetFolderSize(folder, "mp4", false) to get all single folder only
	var totalFileSize = FormatFileSize(bytes);
	Console.WriteLine(totalFileSize);
}

Solution 6 - C#

The short version of the most voted answer has problems with TB values.

I adjusted it appropriately to handle also tb values and still without a loop and also added a little error checking for negative values. Here's my solution:

static readonly string[] SizeSuffixes = { "bytes", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB" };
static string SizeSuffix(long value, int decimalPlaces = 0)
{
	if (value < 0)
	{
		throw new ArgumentException("Bytes should not be negative", "value");
	}
	var mag = (int)Math.Max(0, Math.Log(value, 1024));
	var adjustedSize = Math.Round(value / Math.Pow(1024, mag), decimalPlaces);
	return String.Format("{0} {1}", adjustedSize, SizeSuffixes[mag]);
}

Solution 7 - C#

No. Mostly because it's of a rather niche need, and there are too many possible variations. (Is it "KB", "Kb" or "Ko"? Is a megabyte 1024 * 1024 bytes, or 1024 * 1000 bytes? -- yes, some places use that!)

Solution 8 - C#

Here is an option that's easier to extend than yours, but no, there is none built into the library itself.

private static List<string> suffixes = new List<string> { " B", " KB", " MB", " GB", " TB", " PB" };
public static string Foo(int number)
{
    for (int i = 0; i < suffixes.Count; i++)
    {
        int temp = number / (int)Math.Pow(1024, i + 1);
        if (temp == 0)
            return (number / (int)Math.Pow(1024, i)) + suffixes[i];
    }
    return number.ToString();
}

Solution 9 - C#

@Servy's answer was nice and succinct. I think it can be even simpler?

private static string[] suffixes = new [] { " B", " KB", " MB", " GB", " TB", " PB" };

public static string ToSize(double number, int precision = 2)
{
	// unit's number of bytes
	const double unit = 1024;
	// suffix counter
	int i = 0;
	// as long as we're bigger than a unit, keep going
	while(number > unit)
	{
		number /= unit;
		i++;
	}
	// apply precision and current suffix
	return Math.Round(number, precision) + suffixes[i];
}

Solution 10 - C#

    private string GetFileSize(double byteCount)
    {
        string size = "0 Bytes";
        if (byteCount >= 1073741824.0)
            size = String.Format("{0:##.##}", byteCount / 1073741824.0) + " GB";
        else if (byteCount >= 1048576.0)
            size = String.Format("{0:##.##}", byteCount / 1048576.0) + " MB";
        else if (byteCount >= 1024.0)
            size = String.Format("{0:##.##}", byteCount / 1024.0) + " KB";
        else if (byteCount > 0 && byteCount < 1024.0)
            size = byteCount.ToString() + " Bytes";

        return size;
    }

    private void btnBrowse_Click(object sender, EventArgs e)
    {
        if (openFile1.ShowDialog() == DialogResult.OK)
        {
            FileInfo thisFile = new FileInfo(openFile1.FileName);

            string info = "";

            info += "File: " + Path.GetFileName(openFile1.FileName);
            info += Environment.NewLine;
            info += "File Size: " + GetFileSize((int)thisFile.Length);

            label1.Text = info;
        }
    }

This is one way to do it aswell (The number 1073741824.0 is from 102410241024 aka GB)

Solution 11 - C#

Based on NeverHopeless's elegant solution:

private static readonly KeyValuePair<long, string>[] Thresholds = 
{
    // new KeyValuePair<long, string>(0, " Bytes"), // Don't devide by Zero!
    new KeyValuePair<long, string>(1, " Byte"),
    new KeyValuePair<long, string>(2, " Bytes"),
    new KeyValuePair<long, string>(1024, " KB"),
    new KeyValuePair<long, string>(1048576, " MB"), // Note: 1024 ^ 2 = 1026 (xor operator)
    new KeyValuePair<long, string>(1073741824, " GB"),
    new KeyValuePair<long, string>(1099511627776, " TB"),
    new KeyValuePair<long, string>(1125899906842620, " PB"),
    new KeyValuePair<long, string>(1152921504606850000, " EB"),

    // These don't fit into a int64
    // new KeyValuePair<long, string>(1180591620717410000000, " ZB"), 
    // new KeyValuePair<long, string>(1208925819614630000000000, " YB") 
};

/// <summary>
/// Returns x Bytes, kB, Mb, etc... 
/// </summary>
public static string ToByteSize(this long value)
{
    if (value == 0) return "0 Bytes"; // zero is plural
    for (int t = Thresholds.Length - 1; t > 0; t--)
        if (value >= Thresholds[t].Key) return ((double)value / Thresholds[t].Key).ToString("0.00") + Thresholds[t].Value;
    return "-" + ToByteSize(-value); // negative bytes (common case optimised to the end of this routine)
}

Maybe there are excessive comments, but I tend to leave them to prevent myself from making the same mistakes over on future visits...

Solution 12 - C#

No.

But you can implement like this;

    static double ConvertBytesToMegabytes(long bytes)
    {
	return (bytes / 1024f) / 1024f;
    }

    static double ConvertKilobytesToMegabytes(long kilobytes)
    {
	return kilobytes / 1024f;
    }

Also check out https://stackoverflow.com/questions/565704/how-to-correctly-convert-filesize-in-bytes-into-mega-or-gigabytes

Solution 13 - C#

Updated for C# 9.0 Relational Patterns

public const long OneKB = 1024;

public const long OneMB = OneKB * OneKB;

public const long OneGB = OneMB * OneKB;

public const long OneTB = OneGB * OneKB;

public static string BytesToHumanReadable(ulong bytes)
{
	return bytes switch
	{
		(< OneKB) => $"{bytes}B",
		(>= OneKB) and (< OneMB) => $"{bytes / OneKB}KB",
		(>= OneMB) and (< OneGB) => $"{bytes / OneMB}MB",
		(>= OneGB) and (< OneTB) => $"{bytes / OneMB}GB",
		(>= OneTB) => $"{bytes / OneTB}"
		//...
	};
}

Solution 14 - C#

I have combined some of the answers here into two methods that work great. The second method below will convert from a bytes string (like 1.5.1 GB) back to bytes (like 1621350140) as a long type value. I hope this is useful to others looking for a solution to convert bytes to a string and back into bytes.

public static string BytesAsString(float bytes)
{
    string[] suffix = { "B", "KB", "MB", "GB", "TB" };
    int i;
    double doubleBytes = 0;

    for (i = 0; (int)(bytes / 1024) > 0; i++, bytes /= 1024)
    {
        doubleBytes = bytes / 1024.0;
    }

    return string.Format("{0:0.00} {1}", doubleBytes, suffix[i]);
}

public static long StringAsBytes(string bytesString)
{
    if (string.IsNullOrEmpty(bytesString))
    {
        return 0;
    }

    const long OneKb = 1024;
    const long OneMb = OneKb * 1024;
    const long OneGb = OneMb * 1024;
    const long OneTb = OneGb * 1024;
    double returnValue;
    string suffix = string.Empty;

    if (bytesString.IndexOf(" ") > 0)
    {
        returnValue = float.Parse(bytesString.Substring(0, bytesString.IndexOf(" ")));
        suffix = bytesString.Substring(bytesString.IndexOf(" ") + 1).ToUpperInvariant();
    }
    else
    {
        returnValue = float.Parse(bytesString.Substring(0, bytesString.Length - 2));
        suffix = bytesString.ToUpperInvariant().Substring(bytesString.Length - 2);
    }
        
    switch (suffix)
    {
        case "KB":
            {
                returnValue *= OneKb;
                break;
            }

        case "MB":
            {
                returnValue *= OneMb;
                break;
            }

        case "GB":
            {
                returnValue *= OneGb;
                break;
            }

        case "TB":
            {
                returnValue *= OneTb;
                break;
            }

        default:
            {
                break;
            }
    }

    return Convert.ToInt64(returnValue);
}

Solution 15 - C#

I went for JerKimballs solution, and thumbs up to that. However, I would like to add / point out that this is indeed a matter of controversy as a whole. In my research (for other reasons) I have come up with the following pieces of information.

When normal people (I have heard they exist) speak of gigabytes they refer to the metric system wherein 1000 to the power of 3 from the original number of bytes == the number of gigabytes. However, of course there is the IEC / JEDEC standards which is nicely summed up in wikipedia, which instead of 1000 to the power of x they have 1024. Which for physical storage devices (and I guess logical such as amazon and others) means an ever increasing difference between metric vs IEC. So for instance 1 TB == 1 terabyte metric is 1000 to the power of 4, but IEC officially terms the similar number as 1 TiB, tebibyte as 1024 to the power of 4. But, alas, in non-technical applications (I would go by audience) the norm is metric, and in my own app for internal use currently I explain the difference in documentation. But for display purposes I do not even offer anything but metric. Internally even though it's not relevant in my app I only store bytes and do the calculation for display.

As a side note I find it somewhat lackluster that the .Net framework AFAIK (and I am frequently wrong thank the powers that be) even in it's 4.5 incarnation does not contain anything about this in any libraries internally. One would expect an open source library of some kind to be NuGettable at some point, but I admit this is a small peeve. On the other hand System.IO.DriveInfo and others also only have bytes (as long) which is rather clear.

Solution 16 - C#

How about some recursion:

private static string ReturnSize(double size, string sizeLabel)
{
  if (size > 1024)
  {
    if (sizeLabel.Length == 0)
      return ReturnSize(size / 1024, "KB");
    else if (sizeLabel == "KB")
      return ReturnSize(size / 1024, "MB");
    else if (sizeLabel == "MB")
      return ReturnSize(size / 1024, "GB");
    else if (sizeLabel == "GB")
      return ReturnSize(size / 1024, "TB");
    else
      return ReturnSize(size / 1024, "PB");
  }
  else
  {
    if (sizeLabel.Length > 0)
      return string.Concat(size.ToString("0.00"), sizeLabel);
    else
      return string.Concat(size.ToString("0.00"), "Bytes");
  }
}

Then you can call it:

ReturnSize(size, string.Empty);

Solution 17 - C#

I recently needed this and required to convert the in bytes to a number in long.

Usage: Byte.Kb.ToLong(1) should give 1024.

public enum Byte
{
    Kb,
    Mb,
    Gb,
    Tb
}

public static class ByteSize
{
    private const long OneKb = 1024;
    private const long OneMb = OneKb * 1024;
    private const long OneGb = OneMb * 1024;
    private const long OneTb = OneGb * 1024;

    public static long ToLong(this Byte size, int value)
    {
        return size switch
        {
            Byte.Kb => value * OneKb,
            Byte.Mb => value * OneMb,
            Byte.Gb => value * OneGb,
            Byte.Tb => value * OneTb,
            _ => throw new NotImplementedException("This should never be hit.")
        };
    }
}

Tests using xunit:

[Theory]
[InlineData(Byte.Kb, 1, 1024)]
[InlineData(Byte.Kb, 2, 2048)]
[InlineData(Byte.Mb, 1, 1048576)]
[InlineData(Byte.Mb, 2, 2097152)]
[InlineData(Byte.Gb, 1, 1073741824)]
[InlineData(Byte.Gb, 2, 2147483648)]
[InlineData(Byte.Tb, 1, 1099511627776)]
[InlineData(Byte.Tb, 2, 2199023255552)]
public void ToLong_WhenConverting_ShouldMatchExpected(Byte size, int value, long expected)
{
    var result = size.ToLong(value);

    result.Should().Be(expected);
}

Solution 18 - C#

How about:

public void printMB(uint sizekB)   
{
    double sizeMB = (double) sizekB / 1024;
    Console.WriteLine("Size is " + sizeMB.ToString("0.00") + "MB");
}

E.g. call like

printMB(123456);

Will result in output

"Size is 120,56 MB"

Solution 19 - C#

https://github.com/logary/logary/blob/master/src/Logary/DataModel.fs#L832-L837

let scaleBytes (value : float) : float * string =
    let log2 x = log x / log 2.
    let prefixes = [| ""; "Ki"; "Mi"; "Gi"; "Ti"; "Pi" |] // note the capital K and the 'i'
    let index = int (log2 value) / 10
    1. / 2.**(float index * 10.),
sprintf "%s%s" prefixes.[index] (Units.symbol Bytes)

(DISCLAIMER: I wrote this code, even the code in the link!)

Solution 20 - C#

public static class MyExtension
{
    public static string ToPrettySize(this float Size)
    {
        return ConvertToPrettySize(Size, 0);
    }
    public static string ToPrettySize(this int Size)
    {
        return ConvertToPrettySize(Size, 0);
    }
    private static string ConvertToPrettySize(float Size, int R)
    {
        float F = Size / 1024f;
        if (F < 1)
        {
            switch (R)
            {
                case 0:
                    return string.Format("{0:0.00} byte", Size);
                case 1:
                    return string.Format("{0:0.00} kb", Size);
                case 2:
                    return string.Format("{0:0.00} mb", Size);
                case 3:
                    return string.Format("{0:0.00} gb", Size);
            }
        }
        return ConvertToPrettySize(F, ++R);
    }
}

Solution 21 - C#

As posted above, the recursion is the favorite way, with the help of logarithm.

The following function has 3 arguments : the input, the dimension constraint of the output, that is the third argument.

int ByteReDim(unsigned long ival, int constraint, unsigned long *oval)
{
	int base = 1 + (int) log10(ival);

	(*oval) = ival;
	if (base > constraint) {
		(*oval) = (*oval) >> 10;
		return(1 + ByteReDim((*oval), constraint, oval));
	} else
		return(0);
}

Now let's convert 12GB of RAM in several units:

int main(void)
{
	unsigned long RAM;
	int unit; // index of below symbols array
	char symbol[5] = {'B', 'K', 'M', 'G', 'T'};

	unit = ByteReDim(12884901888, 12, &RAM);
	printf("%lu%c\n", RAM, symbol[unit]); // output is 12884901888B

	unit = ByteReDim(12884901888, 9, &RAM);
	printf("%lu%c\n", RAM, symbol[unit]); // output is 12582912K

	unit = ByteReDim(12884901888, 6, &RAM);
	printf("%lu%c\n", RAM, symbol[unit]); // output is 12288M

	unit = ByteReDim(12884901888, 3, &RAM);
	printf("%lu%c\n", RAM, symbol[unit]); // output is 12G
}

Solution 22 - C#

I use this for Windows (binary prefixes):

static readonly string[] BinaryPrefix = { "bytes", "KB", "MB", "GB", "TB" }; // , "PB", "EB", "ZB", "YB"
string GetMemoryString(double bytes)
{
    int counter = 0;
    double value = bytes;
    string text = "";
    do
    {
        text = value.ToString("0.0") + " " + BinaryPrefix[counter];
        value /= 1024;
        counter++;
    }
    while (Math.Floor(value) > 0 && counter < BinaryPrefix.Length);
    return text;
}

Solution 23 - C#

I have incorporated this (with little to no modification) into a UWP DataBinding Converter for my project and thought it might also be useful to others.

The code is:

using System;
using System.Text;
using Windows.UI.Xaml.Data;

namespace MyApp.Converters
{
    public class ByteSizeConverter : IValueConverter
    {
        static readonly string[] sSizeSuffixes = { "bytes", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB" };

        // The number of decimal places the formatter should include in the scaled output - default 1dp
        public int DecimalPlaces { get; set; } = 1;

        public object Convert(object value, Type targetType, object parameter, string language)
        {
            Int64 intVal = System.Convert.ToInt64(value);

            return SizeSuffix(intVal);
        }

        public object ConvertBack(object value, Type targetType, object parameter, string language)
        {
            // TODO: Parse string into number and suffix
            //       Scale number by suffix multiplier to get bytes
            throw new NotImplementedException();
        }

        string SizeSuffix(Int64 value)
        {
            if (this.DecimalPlaces < 0) { throw new ArgumentOutOfRangeException(String.Format("DecimalPlaces = {0}", this.DecimalPlaces)); }
            if (value < 0) { return "-" + SizeSuffix(-value); }
            if (value == 0) { return string.Format("{0:n" + this.DecimalPlaces + "} bytes", 0); }

            // magnitude is 0 for bytes, 1 for KB, 2, for MB, etc.
            int magnitude = (int)Math.Log(value, 1024);
            // clip magnitude - only 8 values currently supported, this prevents out-of-bounds exception
            magnitude = Math.Min(magnitude, 8);
            
            // 1L << (magnitude * 10) == 2 ^ (10 * magnitude) [i.e. the number of bytes in the unit corresponding to magnitude]
            decimal adjustedSize = (decimal)value / (1L << (magnitude * 10));

            // make adjustment when the value is large enough that it would round up to 1000 or more
            if (Math.Round(adjustedSize, this.DecimalPlaces) >= 1000)
            {
                magnitude += 1;
                adjustedSize /= 1024;
            }

            return String.Format("{0:n" + this.DecimalPlaces + "} {1}", adjustedSize, sSizeSuffixes[magnitude]);
        }
    }
}

To use it, add a local resource to your UserControl or Page XAML:

<UserControl.Resources>
    <converters:ByteSizeConverter x:Key="ByteFormat" DecimalPlaces="3" />
</UserControl.Resources>

Reference it in a data binding template or data binding instance:

<TextBlock HorizontalAlignment="Left" VerticalAlignment="Center"
    Text="{x:Bind MyItem.FileSize_bytes, Mode=OneWay, Converter={StaticResource ByteFormat}}" />

And hey presto. The magic happens.

Solution 24 - C#

Here's my spin on @drzaus's answer. I modified it to use rounding errors to our advantage and correctly manage issues around unit boundaries. It also handles negative values.

Drop this C# Program into LinqPad:

// Kudos: https://stackoverflow.com/a/48467634/117797

void Main()
{
	0.ToFriendly().Dump();						// 0 B
	857.ToFriendly().Dump();					// 857 B
	(173*1024).ToFriendly().Dump();				// 173 KB
	(9541*1024).ToFriendly().Dump();			// 9.32 MB
	(5261890L*1024).ToFriendly().Dump();		// 5.02 GB

	1.ToFriendly().Dump();						// 1 B
	1024.ToFriendly().Dump();                	// 1 KB
	1048576.ToFriendly().Dump();             	// 1 MB
	1073741824.ToFriendly().Dump();          	// 1 GB
	1099511627776.ToFriendly().Dump();       	// 1 TB
	1125899906842620.ToFriendly().Dump();    	// 1 PB
	1152921504606850000.ToFriendly().Dump(); 	// 1 EB
}

public static class Extensions
{
	static string[] _byteUnits = new[] { "B", "KB", "MB", "GB", "TB", "PB", "EB" };

	public static string ToFriendly(this int number, int decimals = 2)
	{
		return ((double)number).ToFriendly(decimals);
	}

	public static string ToFriendly(this long number, int decimals = 2)
	{
		return ((double)number).ToFriendly(decimals);
	}

	public static string ToFriendly(this double number, int decimals = 2)
	{
		const double divisor = 1024;

		int unitIndex = 0;
		var sign = number < 0 ? "-" : string.Empty;
		var value = Math.Abs(number);
		double lastValue = number;

		while (value > 1)
		{
			lastValue = value;

			// NOTE
			// The following introduces ever increasing rounding errors, but at these scales we don't care.
			// It also means we don't have to deal with problematic rounding errors due to dividing doubles.
			value = Math.Round(value / divisor, decimals);

			unitIndex++;
		}

		if (value < 1 && number != 0)
		{
			value = lastValue;
			unitIndex--;
		}

		return $"{sign}{value} {_byteUnits[unitIndex]}";
	}
}

Output is:

0 B
857 B
173 KB
9.32 MB
1.34 MB
5.02 GB
1 B
1 KB
1 MB
1 GB
1 TB
1 PB
1 EB

Solution 25 - C#

string Convert(float bytes)
{
	string[] Group = { "Bytes", "KB", "MB", "GB", "TB"};
	float B = bytes; int G = 0;
	while (B >= 1024 && G < 5)
	{
		B /= 1024;
		G += 1;
	}
	float truncated = (float)(Math.Truncate((double)B * 100.0) / 100.0);
	string load = (truncated + " " + Group[G]);

	return load;
}

Solution 26 - C#

This is how I do it.

Console.Write(FileSizeInBytes > 1048576 ? FileSizeInBytes / 1048576f + " MB" : FileSizeInBytes / 1024f + " KB"); //1048576 = 1024 * 1024

Solution 27 - C#

I combined zackmark15's code into an all-purpose file or directory measuring approach:

public static string PathSize(string path)
{
    if (String.IsNullOrEmpty(path))
        throw new ArgumentNullException(nameof(path));

    long bytes;

    if (File.Exists(path))
        bytes = new FileInfo(path).Length;

    else if (Directory.Exists(path))
        bytes = new DirectoryInfo(path).EnumerateFiles("*", SearchOption.AllDirectories).Sum(fileInfo => fileInfo.Length);

    else
        throw new ArgumentException("Path does not exist.", nameof(path));

    const long UNIT = 1024L;

    if (bytes < UNIT)
        return $"{bytes} bytes";

    var exp = (int)(Math.Log(bytes) / Math.Log(UNIT));

    return $"{bytes / Math.Pow(UNIT, exp):F2} {("KMGTPE")[exp - 1]}B";
}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionJohn SmithView Question on Stackoverflow
Solution 1 - C#JLRisheView Answer on Stackoverflow
Solution 2 - C#OmarView Answer on Stackoverflow
Solution 3 - C#NeverHopelessView Answer on Stackoverflow
Solution 4 - C#JerKimballView Answer on Stackoverflow
Solution 5 - C#zackmark15View Answer on Stackoverflow
Solution 6 - C#RoemerView Answer on Stackoverflow
Solution 7 - C#James CurranView Answer on Stackoverflow
Solution 8 - C#ServyView Answer on Stackoverflow
Solution 9 - C#drzausView Answer on Stackoverflow
Solution 10 - C#LobbeView Answer on Stackoverflow
Solution 11 - C#Louis SomersView Answer on Stackoverflow
Solution 12 - C#Soner GönülView Answer on Stackoverflow
Solution 13 - C#CryolithicView Answer on Stackoverflow
Solution 14 - C#mesterakView Answer on Stackoverflow
Solution 15 - C#randomSheepleView Answer on Stackoverflow
Solution 16 - C#RooiWillieView Answer on Stackoverflow
Solution 17 - C#QuestioningView Answer on Stackoverflow
Solution 18 - C#BoernView Answer on Stackoverflow
Solution 19 - C#HenrikView Answer on Stackoverflow
Solution 20 - C#phucngView Answer on Stackoverflow
Solution 21 - C#CyrIngView Answer on Stackoverflow
Solution 22 - C#A.J.BauerView Answer on Stackoverflow
Solution 23 - C#FunkyLobster27View Answer on Stackoverflow
Solution 24 - C#ZodmanView Answer on Stackoverflow
Solution 25 - C#joanView Answer on Stackoverflow
Solution 26 - C#Naresh BishtView Answer on Stackoverflow
Solution 27 - C#FocusedWolfView Answer on Stackoverflow