It’s been a very long day, so it’s likely I need to go home and have a beer instead of doing this, but I’d love to wrap up something I’ve been working on first.
I’ve got a method to format bytes into a more human-readable number. This seems like a perfect place for a Select Case statment, which I don’t use very often but would like to, because they’re so much cleaner than nested if/then statements in situations like this.
fileSize is an int64 that’s passed into the method. I’m testing on a file set that’s more than 5GB (fileSize = 5650440192)
[code]dim ext as string
select case fileSize
Case Is < 1024
ext = " Bytes"
Case Is < 1024 * 1024
fileSize = fileSize/1024
ext = " KB"
Case Is < 1024 * 1024 * 1024
fileSize = fileSize/1024/1024
ext = " MB"
Case Is < 1024 * 1024 * 1024 * 1024
fileSize = fileSize/1024/1024/1024
ext = " GB"
Case Is < 1024 * 1024 * 1024 * 1024 *1024
fileSize = fileSize/1024/1024/1024/1024
ext = " TB"
else
break
end select
return fileSize.ToText + ext
[/code]
It always breaks at the else statement, never satisfying any of the cases. Am I missing something obvious here? (likely, but I just can’t see it)
Thanks
32 or 64-bit compilation?
Uh yeah. Make filesize a UInt64. An Int64 would roll over.
Thanks - the project was set to 32bit though I thought I had set it to 64 when setting it up.
Now for that beer…
Try this:
[code] // Param fileSize As Int64
// Return: String // Size rounded shorter
Dim ext as string
Const kbVal As Int64 = 1024
Const mbVal As Int64 = kbVal * 1024
Const gbVal As Int64 = mbVal * 1024
Const tbVal As Int64 = gbVal * 1024
Const ptVal As Int64 = tbVal * 1024
Dim fileSizeDecs As Double = fileSize
Select Case fileSize
Case Is < kbVal
ext = “Bytes”
Case Is < mbVal
fileSizeDecs = fileSize / kbVal
ext = “KB”
Case Is < gbVal
fileSizeDecs = fileSize / mbVal
ext = “MB”
Case Is < tbVal
fileSizeDecs = fileSize / gbVal
ext = “GB”
Case Is < ptVal
fileSizeDecs = fileSize / tbVal
ext = “TB”
else
ext = “Overflow!”
End select
Return fileSizeDecs.ToText(Xojo.Core.Locale.Current, "#,##0.## ")+ext
[/code]
Xojo maybe isn’t promoting the internal math to the larger correct container and losing accuracy. Using int64 pre-calculated consts you probably will force 64 bit math instead of 32 bit. That’s what I suppose based on past errors, not sure if this is your case. Not tested, test please.
I just replaced my code with yours and the result is better - Mine was telling me the 5.26GB test file set was 5GB (which I figured was something I’d have to look into tomorrow). Yours is telling me it’s 5.26GB.
Plus yours is cleaner. I prefer it to my “1024 * 1024 * 1024 * 1024” mess.
Thanks!
Your code was truncating the math, I made mine floating point and exposed 2 decimals.
Smaller, no Select. Accept Petabytes. Made just for fun.
Private Function ApproximateBytesString(numBytes As UInt64) As String
Dim MemUnit() As String = Array("Overflow","Bytes","KB","MB","GB","TB","PB")
Dim unit As Integer = 0
Dim unitVal As Double = numBytes
For i As Integer = 1 to 6
If unitVal < 1024.0 Then
unit = i
Exit
End
unitVal = unitVal / 1024.0
Next
Return unitVal.ToText(Xojo.Core.Locale.Current, "#,##0.## ")+MemUnit(unit)
End Function