Welcome to my site!

Chatelherault Country Park

Chatelherault Country Park is a country park in Hamilton, South Lanarkshire, Scotland. It is centred on the former hunting lodge, a folly designed to be seen from the now demolished Hamilton Palace at the end of a broad grass slope forming an avenue with lines of lime trees.

Comments
  1. Ken
    Ken

    I think the newer solution is slower and incorrect.

    [Fact]
    public void ShouldFormatGigabytes()
    {
    const long sut = 1 * 1024 * 1024 * 1024;
    Assert.Equal("1 GB", FormatBytes(sut));
    }

    Actual: 1024 MB

  2. BK
    BK

    Another refactoring without the loop (in VB):
    Private Function FormatBytes(ByVal bytes As Long) As String
    Const scale = 1024
    Dim orders As String() = New String() {"", "K", "M", "G", "T", "P", "E"}

    Dim rank = Math.Floor(Math.Log(bytes, scale))
    If rank >= orders.Length Then rank -= 1
    Return String.Format("{0:##.##} {1}B", bytes / Math.Pow(scale, rank), orders(rank))
    End Function

  3. Paul
    Paul

    if (bytes == max) return string.Format("1 {0}", order);

  4. Steven Hartgers
    Steven Hartgers

    I got the ultimate solution:

    return (String.Format("{0:##.##0}",
    Bytes >= 1073741824 ? decimal.Divide(Bytes, 1073741824) + "GB" :
    Bytes >= 1048576 ? decimal.Divide(Bytes, 1048576) + "MB" :
    Bytes >= 1024 ? decimal.Divide(Bytes, 1024) + "KB" :
    Bytes > 0 & Bytes < 1024 ? Bytes + "Bytes" : 0 + "0 Bytes"
    ));

    Happy formating :)

  5. ian
    ian

    So I used this in a console app recently as well, here was my function.. just to wrap it up..

    static string FormatBytes(long bytes)
    {
    const long scale = 1024;
    string[] orders = new string[]{ "YB", "ZB", "EB", "PB", "TB", "GB", "MB", "KB", "Bytes" };
    var max = (long)Math.Pow(scale, (orders.Length - 1));
    foreach (string order in orders)
    {
    if (bytes > max)
    return string.Format("{0:##.##} {1}", Decimal.Divide(bytes, max), order);
    max /= scale;
    }
    return "0 Bytes";
    }

    1. ian
      ian

      Okay so this actually only works up to the EB's, it kind of looks like somewhere between EB's and ZB's we hit the max value for the long data type, and the previous function would return just "YB" for all of the string values. So I modified the orders array to this:

      string[] orders = new string[]{ "EB", "PB", "TB", "GB", "MB", "KB", "Bytes" };

      You could try a different data type, but I'm not measuring anything larger than EB's anyways.

  6. Ross
    Ross

    Hi, nice code, thanks!

    I also changed this line to do a little future proofing for Diomede Storage. :)

    string[] orders = new string[] { "YB", "ZB", "EB", "PB", "TB", "GB", "MB", "KB", "Bytes" };

    -- Ross

    1. Shimmy
      Shimmy

      @Ross what about Brontobytes? :-)

  7. Ian
    Ian

    thanks code worked great. if your bytes are displayed in MB like mine were all you have to do is modify the scale..mine looked something like scale = (1024/10) or you could go the other way scale = 10240

    awesome code thanks a bunch.

  8. Ben Laan
    Ben Laan

    This code has 4 repeating blocks! Sounds like it needs a good refactoring:

    public string FormatBytesNew( long bytes )
    {
    const int scale = 1024;

    var orders = new[] { "GB", "MB", "KB", "Bytes" };
    var max = (long) Math.Pow( scale, orders.Length - 1 );

    foreach ( var order in orders )
    {
    if ( bytes > max )
    return string.Format( "{0:##.##} {1}", Decimal.Divide( bytes, max ), order );

    max /= scale;
    }
    return "0 Bytes";
    }

  9. Tim Trott
    Tim Trott

    Hi ben,

    Thanks for the refactor!

    I wasn't completely happy with the code, especially the hard coded byte values; however I copied if from the somewhere on the web and just carried on using it. "If it ain't broke, don't fix it".

    I will probably give your version a try though!

    Thanks

Leave a Reply

Your email address will not be published.