There are several ways to do this. One that caught my eye was the deepee1 method . I made a small adjustment and put this method into a extension methods class.
public static partial class NumericExtender
{
private static IList<string> fileSizeUnits;
static NumericExtender()
{
fileSizeUnits =
new List<string>() { "B", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB" };
}
/// <summary>
/// Retorna o valor formatado como tamanho de arquivo (KB, MB, GB...).
/// </summary>
/// <param name="totalBytes">Total de bytes do arquivo.</param>
/// <param name="precision">Número de casas decimais para exibir.</param>
/// <returns>Tamanho do arquivo formatado.</returns>
public static string ToFileSize(this double totalBytes, int precision = 2)
{
if (totalBytes <= 0)
return String.Format("0 {0}", fileSizeUnits[0]);
double bytes = Math.Abs(totalBytes);
int place = Convert.ToInt32(Math.Floor(Math.Log(bytes, 1024)));
if (place > fileSizeUnits.Count - 1)
place = fileSizeUnits.Count - 1;
double num = Math.Round(bytes / Math.Pow(1024, place), precision);
return String.Format("{0} {1}", Math.Sign(totalBytes) * num, fileSizeUnits[place]);
}
}
And I did a test method:
[TestMethod]
public void ToFileSize()
{
Assert.AreEqual("0 B", Int32.MinValue.ToFileSize());
Assert.AreEqual("0 B", UInt32.MinValue.ToFileSize());
Assert.AreEqual("0 B", Int64.MinValue.ToFileSize());
Assert.AreEqual("0 B", UInt64.MinValue.ToFileSize());
Assert.AreEqual("0 B", Double.MinValue.ToFileSize());
Assert.AreEqual("2 GB", Int32.MaxValue.ToFileSize());
Assert.AreEqual("4 GB", UInt32.MaxValue.ToFileSize());
Assert.AreEqual("8 EB", Int64.MaxValue.ToFileSize());
Assert.AreEqual("16 EB", UInt64.MaxValue.ToFileSize());
Assert.AreEqual("1.48701690847778E+284 YB", Double.MaxValue.ToFileSize());
Assert.AreEqual("1.24 KB", 1270.ToFileSize());
Assert.AreEqual("1.24023 KB", 1270.ToFileSize(5));
}