How to return KB, MB and GB from Bytes using a public function

29,352

Solution 1

I would use a select case for it and not a if.
And always start with the biggest size." i stopped at TB but of Corse you can add more if you need ..."

I changed Dim TheSize As Integer to "Dim TheSize As ULong " otherwise big numbers don't work.

Also make a dim "Dim DoubleBytes As Double" you will use it in the select case.

First you compare the bytes you have with a case , lets say mb "Case 1048576 To 1073741823"
So if this is the case convert TheSize to a double "DoubleBytes = CDbl(TheSize / 1048576) 'MB "

Then in the return you use FormatNumber to set the number you want to show behind the . "the nuber 2 is to set it to 2 behind the . like 28.11 , change it to 0 and it will return 28" also because you know it mb you wil add & mb to the return.
"Return FormatNumber(DoubleBytes, 2) & " MB" "

Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    MsgBox(GetFileSize("E:\Software\TeamSpeak3-Client-win64-3.0.14.exe"))
End Sub

Dim DoubleBytes As Double

Public Function GetFileSize(ByVal TheFile As String) As String
    If TheFile.Length = 0 Then Return ""
    If Not System.IO.File.Exists(TheFile) Then Return ""
    '---
    Dim TheSize As ULong = My.Computer.FileSystem.GetFileInfo(TheFile).Length
    Dim SizeType As String = ""
    '---

    Try
        Select Case TheSize
            Case Is >= 1099511627776
                DoubleBytes = CDbl(TheSize / 1099511627776) 'TB
                Return FormatNumber(DoubleBytes, 2) & " TB"
            Case 1073741824 To 1099511627775
                DoubleBytes = CDbl(TheSize / 1073741824) 'GB
                Return FormatNumber(DoubleBytes, 2) & " GB"
            Case 1048576 To 1073741823
                DoubleBytes = CDbl(TheSize / 1048576) 'MB
                Return FormatNumber(DoubleBytes, 2) & " MB"
            Case 1024 To 1048575
                DoubleBytes = CDbl(TheSize / 1024) 'KB
                Return FormatNumber(DoubleBytes, 2) & " KB"
            Case 0 To 1023
                DoubleBytes = TheSize ' bytes
                Return FormatNumber(DoubleBytes, 2) & " bytes"
            Case Else
                Return ""
        End Select
    Catch
        Return ""
    End Try
End Function

I made a dll for it.
Then I can import it to my project and I can call it whenever I need to change a byte number to something else "like mb etc"
FormatBytes(GetHDSizeF) "GetHDSizeF is the number of bytes"

Dim DoubleBytes As Double
Default Public Property FormatBytes(ByVal BytesCaller As ULong) As String
    Get
        Try
            Select Case BytesCaller
                Case Is >= 1099511627776
                    DoubleBytes = CDbl(BytesCaller / 1099511627776) 'TB
                    Return FormatNumber(DoubleBytes, 2) & " TB"
                Case 1073741824 To 1099511627775
                    DoubleBytes = CDbl(BytesCaller / 1073741824) 'GB
                    Return FormatNumber(DoubleBytes, 2) & " GB"
                Case 1048576 To 1073741823
                    DoubleBytes = CDbl(BytesCaller / 1048576) 'MB
                    Return FormatNumber(DoubleBytes, 2) & " MB"
                Case 1024 To 1048575
                    DoubleBytes = CDbl(BytesCaller / 1024) 'KB
                    Return FormatNumber(DoubleBytes, 2) & " KB"
                Case 0 To 1023
                    DoubleBytes = BytesCaller ' bytes
                    Return FormatNumber(DoubleBytes, 2) & " bytes"
                Case Else
                    Return ""
            End Select
        Catch
            Return ""
        End Try
    End Get
    Set(value As String)

    End Set
End Property

And if you don't want to make a dll you can use it like a normal function like this.

Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    MsgBox(FormatBytes(2000))
End Sub

Dim DoubleBytes As Double
Public Function FormatBytes(ByVal BytesCaller As ULong) As String

    Try
        Select Case BytesCaller
            Case Is >= 1099511627776
                DoubleBytes = CDbl(BytesCaller / 1099511627776) 'TB
                Return FormatNumber(DoubleBytes, 2) & " TB"
            Case 1073741824 To 1099511627775
                DoubleBytes = CDbl(BytesCaller / 1073741824) 'GB
                Return FormatNumber(DoubleBytes, 2) & " GB"
            Case 1048576 To 1073741823
                DoubleBytes = CDbl(BytesCaller / 1048576) 'MB
                Return FormatNumber(DoubleBytes, 2) & " MB"
            Case 1024 To 1048575
                DoubleBytes = CDbl(BytesCaller / 1024) 'KB
                Return FormatNumber(DoubleBytes, 2) & " KB"
            Case 0 To 1023
                DoubleBytes = BytesCaller ' bytes
                Return FormatNumber(DoubleBytes, 2) & " bytes"
            Case Else
                Return ""
        End Select
    Catch
        Return ""
    End Try

End Function

Solution 2

You need to divide by 1024 not 1000. 1 KB is not 1000 Bytes, it's 1024 bytes. 1 MB is not 1000 KB, it's 1024 KB, and so on.

Here's a good site to explain all this: http://pc.net/helpcenter/answers/why_1024_bytes

Solution 3

Here is how I do it, below is a VBA function that I use in Microsoft Access that can easily be converted to VB or VBScript, etc.

Public Function FormatFileSize(ByVal lngFileSize As Long) As String

  Dim x      As Integer:      x = 0
  Dim Suffix As String:  Suffix = ""
  Dim Result As Single:  Result = lngFileSize

  Do Until Int(Result) < 1000
     x = x + 1
     Result = Result / 1024
  Loop

  Result = Round(Result, 2)

  Select Case x
         Case 0
              Suffix = "Bytes"
         Case 1 'KiloBytes
              Suffix = "KB"
         Case 2 'MegaBytes
              Suffix = "MB"
         Case 3 'GigaBytes
              Suffix = "GB"
         Case 4 'TeraBytes
              Suffix = "TB"
         Case 5 'PetaBytes
              Suffix = "PB"
         Case 6 'ExaBytes
              Suffix = "EB"
         Case 7 'ZettaBytes
              Suffix = "ZB"
         Case 8 'YottaBytes
              Suffix = "YB"
         Case Else
              Suffix = "Too big to compute :)"
  End Select

  FormatFileSize = Format(Result, "#,##0.00") & " " & Suffix

End Function 'FormatFileSize

Solution 4

this post helped me out when I was trying to sort this out Learning C#, I usually use VB. Anyway I thought I'd post my update in case anyone cares to use it. It is in VB as I have a library of useful Functions and Subs that I use to keep this stuff in, And I started it in VB and too lazy to change all that code. It works well for me, so I hope it helps someone out.

Function ByteConv(Bytes As Double, Optional Style As Integer = 1) As String

    Dim count As Integer = 0
    Dim factor As Integer = 1024
    Dim Workingnum As Double = Bytes
    Dim Suffix() As String = {"Bytes", "Kb", "Mb", "Tb", "Pb", "Eb"} 'Dimention the string array upto Exobyte .. Cos why not?'

    If Style - 1 Then factor = 1000 Else factor = 1024  'This allows for Function to be used for Comms Calculations. I.e So it returns 100MB connection rather than 95.37'

    While Workingnum > factor And count < 5             'Basically keep dividing the Bytecount by the factor until the result reaches a whole number less that the factor itself'
        Workingnum = Workingnum / factor                ' '
        count = count + 1
    End While
    Return Workingnum.ToString("N") + Suffix(count)     ' Then return a string that includes the result and the applicable suffix.'
End Function

Solution 5

This is an example of what I meant in my comment:

Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click

    If OpenFileDialog1.ShowDialog() = Windows.Forms.DialogResult.OK Then
        Dim CalculatedSize As Decimal
        Dim TheSize As Long = Long.Parse(My.Computer.FileSystem.GetFileInfo(OpenFileDialog1.FileName).Length)
        Dim SizeType As String = "B"

        If TheSize < 1024 Then
            CalculatedSize = TheSize

        ElseIf TheSize > 1024 AndAlso TheSize < (1024 ^ 2) Then 'KB
            CalculatedSize = Math.Round((TheSize / 1024), 2)
            SizeType = "KB"

        ElseIf TheSize > (1024 ^ 2) AndAlso TheSize < (1024 ^ 3) Then 'MB
            CalculatedSize = Math.Round((TheSize / (1024 ^ 2)), 2)
            SizeType = "MB"

        ElseIf TheSize > (1024 ^ 3) AndAlso TheSize < (1024 ^ 4) Then 'GB
            CalculatedSize = Math.Round((TheSize / (1024 ^ 3)), 2)
            SizeType = "GB"

        ElseIf TheSize > (1024 ^ 4) Then 'TB
            CalculatedSize = Math.Round((TheSize / (1024 ^ 4)), 2)
            SizeType = "TB"

        End If

        MessageBox.Show("File size is: " & CalculatedSize.ToString & " " & SizeType, "File size", MessageBoxButtons.OK, MessageBoxIcon.Information)
    End If
End Sub

Result:

File Sizes example

Share:
29,352
Mean Mr Mustard
Author by

Mean Mr Mustard

Updated on November 19, 2020

Comments

  • Mean Mr Mustard
    Mean Mr Mustard over 3 years

    I'm writing a "function" that returns a file's size (in B, KB, MB, GB).

    The VB.Net code always gets the size in bytes first, so when a file's size (in Bytes) is less than 100 it returns B, if its > 1000 then I divide it by 1000 and it returns KB. But when it should be MB I try dividing by 1000000 and the size it returns always comes out 2 MBs bigger than what it should be!?

    Can someone please tell me what I'm doing wrong!!

    Example

    My files size is (15,570,550 Bytes) ..which is.. (14.8 MB)

    So when i run it through this function it returns 16MB!

    The Code

    Public Function GetFileSize(ByVal TheFile As String, _
                                Optional ByVal ShowSizeType As Boolean = False) As String
        If TheFile.Length = 0 Then Return ""
        If Not System.IO.File.Exists(TheFile) Then Return ""
        '---
        Dim TheSize As Integer = My.Computer.FileSystem.GetFileInfo(TheFile).Length
        Dim SizeType As String = ""
        '---
        If TheSize < 1000 Then
            SizeType = "B"
        Else
            If TheSize < 1000000000 Then
                If TheSize < 1000000 Then
                    SizeType = "KB"
                    TheSize = TheSize / 1000
                Else
                    SizeType = "MB"
                    TheSize = TheSize / 1000000
                End If
            Else
                SizeType = "GB"
    
            End If
        End If
        '---
        If ShowSizeType = True Then
            Return TheSize & SizeType
        Else
            Return TheSize
        End If
    End Function
    
    • War10ck
      War10ck over 9 years
      Computers use binary. Binary = Base 2...Decimal = Base 10. You should be using 2^x...
    • Chase Rocker
      Chase Rocker over 9 years
      Read what others have posted, but to answer your specific question: it's rounding 15570550/1000000 which is 15.57 up to 16 to store it in your integer variable.
    • Visual Vincent
      Visual Vincent over 9 years
      Do as roryap said. Divide it by 1024. Also, to make the code a little more simple, use (1024 ^ 2) for example instead of calculating it like 1 048 576. AND if you want the output to have a decimal, you can declare TheSize as a decimal instead and use TheSize = Math.Round(TheSize / (1024 ^ 2), 1)
  • HackSlash
    HackSlash almost 6 years
    This is way better than a select case. This works the same way you might do on paper.
  • J. Scott Elblein
    J. Scott Elblein about 5 years
    Just to confirm, shouldn't If Style - 1 be If Style = -1 ? With Option Strict On you'll get an error otherwise. I rewrote that bit into a ternary (I like ternaries :P) factor = If(intStyle = -1, 1000, 1024)
  • Jim M
    Jim M almost 5 years
    Did you forget Gb in your Suffix() array?