|
-
Jul 3rd, 2019, 10:21 AM
#1
Thread Starter
Fanatic Member
Division causes overflow
Hello!
I have the following function to return the size of a file to me.
Optionally, I want to have MB returned instead of KB.
The first thing that I stumbled over was a file length > 2 GB.
To work around this, I found the following hack: lRet = 2147483648# + (2147483648# - Abs(lRet))
However, when I then divide this value (for example: 2438086656) by 1000000, I get an overflow exception.
Can anybody tell me what I'm doing wrong here?
Thank you!
Code:
Public Function FileLength(ByVal uPath As String, ByVal uMBInsteadOfByte As Boolean, ByVal uCaller As String) As Currency
On Error GoTo ErrHandler
Debug.Print "Getting filelen from " & uPath
Debug.Assert modIO.FileExists(uPath)
Dim ret As Currency 'We could have used Long here, but if ret < 0, then we need to add a huge number
ret = VBA.FileLen(uPath)
If ret < 0 Then
'bigger than 2 gb
ret = 2147483648# + (2147483648# - Abs(ret)) 'Not sure what I'm doing here, I copied it from the internet
End If
Debug.Assert ret > 0
If uMBInsteadOfByte Then
ret = (ret \ 1000000) 'this causes an overflow exception. I don't see why.
End If
FileLength = ret
Exit Function
ErrHandler:
Debug.Print Err.Description
Call WriteLog("#FileLength: " & Err.Description & ", err.number: " & Err.Number & ", Params: '" & uPath & "', caller: " & uCaller)
On Error GoTo -1
Debug.Assert False
End Function
-
Jul 3rd, 2019, 10:38 AM
#2
Re: Division causes overflow
The reason for the error is that integer division is used (\). Use (/) instead
-
Jul 3rd, 2019, 11:04 AM
#3
Re: Division causes overflow
The FileLen() function doesn't handle huge files.
Assuming there is really any need for this at all, I'd probably choose something like this:
Code:
Option Explicit
Private Const GENERIC_READ As Long = &H80000000
Private Const OPEN_ALWAYS = 4
Public Enum SHARE_MODES
FILE_SHARE_EXCLUSIVE = 0
FILE_SHARE_READ = 1
FILE_SHARE_WRITE = 2
FILE_SHARE_DELETE = 4
FILE_SHARE_ALL = FILE_SHARE_READ Or FILE_SHARE_WRITE Or FILE_SHARE_DELETE
End Enum
#If False Then
Dim FILE_SHARE_EXCLUSIVE, FILE_SHARE_READ, FILE_SHARE_WRITE, FILE_SHARE_DELETE, FILE_SHARE_ALL
#End If
Private Declare Function CloseHandle Lib "kernel32" ( _
ByVal hObject As Long) As Long
Private Declare Function CreateFile Lib "kernel32" Alias "CreateFileW" ( _
ByVal lpFileName As Long, _
ByVal dwDesiredAccess As Long, _
ByVal dwShareMode As SHARE_MODES, _
ByVal lpSecurityAttributes As Long, _
ByVal dwCreationDisposition As Long, _
ByVal dwFlagsAndAttributes As Long, _
ByVal hTemplateFile As Long) As Long
Private Declare Function GetFileSizeEx Lib "kernel32" ( _
ByVal hFile As Long, _
ByRef curFileSize As Currency) As Long
Private Sub Form_Load()
Const TEST_FILE As String = "D:\VHDs\Vista w IE8\Vista SP1 x86 with IE8 2009-Apr.vhd"
Dim hFile As Long
Dim curFileSize As Currency
Dim MBFileSize As Double
hFile = CreateFile(StrPtr(TEST_FILE), _
GENERIC_READ, _
FILE_SHARE_ALL, _
0&, _
OPEN_ALWAYS, _
0&, _
0&)
GetFileSizeEx hFile, curFileSize
CloseHandle hFile
MBFileSize = CDbl(curFileSize) / (1000000 / 10000)
AutoRedraw = True
ScaleLeft = -60
ScaleTop = -60
Cls
Print TEST_FILE
Print Format$(MBFileSize, "#,##0.000 \M\B")
End Sub
That uses a Currency as a stand-in for a 64-bit integer type. The result is converted to a Double (or you might use a Decimal Variant) and then corrected by 10000 before finally dividing by 1000000.
-
Jul 3rd, 2019, 11:06 AM
#4
Re: Division causes overflow
You might also want to show more detail:
Code:
Print Format$(MBFileSize, "#,##0.000000 \M\B")
-
Jul 3rd, 2019, 11:08 AM
#5
Thread Starter
Fanatic Member
Re: Division causes overflow
Thanks both of you very much!
Tags for this Thread
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|