News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

Best way to determine file length??

Started by Astro, February 20, 2010, 05:27:52 PM

Previous topic - Next topic

Astro

Hi,

Are there any better ways to determine file length than iterating ReadFile until it hits EOF?

EDIT: D'oh!!!! GetFileSize.  :boohoo:

Best regards,
Robin.


Astro


Astro

Whoa... I get weird behavior:

    assume edx:ptr _LARGE_INTEGER
    lea edx,LargeInteger
    print str$([edx].LowPart)
    assume edx:nothing

prints '4' as expected.

    assume edx:ptr _LARGE_INTEGER
    lea edx,LargeInteger
    print str$([edx].HighPart)
    assume edx:nothing

prints '0' as expected.

But.......

    assume edx:ptr _LARGE_INTEGER
    lea edx,LargeInteger
    print str$([edx].HighPart)
    print str$([edx].LowPart)
    assume edx:nothing

prints the strange number '0614763971'.  :eek

Best regards,
Robin.

dedndave

the first "print" probably destroys the contents of EDX

push edx
print.....
pop edx
print....

jj2007

Quote from: Astro on February 20, 2010, 05:27:52 PM
EDIT: D'oh!!!! GetFileSize.  :boohoo:

FindFirstFile: WIN32_FIND_DATA.nFileSizeLow

Over a network share, CreateFile then GetFileSize is dozens of times slower than just using FindFirstFile to get at the size
http://msdn.microsoft.com/en-us/library/aa364955%28VS.85%29.aspx

BlackVortex

Interesting. I think GetFileAttributesEx is also a great choice, according to the same person, what do you think ?

Better to use 1 API call than 2, that's for sure.

evlncrn8

or FindFirstFileA / FindFirstFileW - which gives more information than the other api's such as file create time, size, last write time etc.. :)

BlackVortex

Quote from: evlncrn8 on February 21, 2010, 01:00:32 PM
or FindFirstFileA / FindFirstFileW - which gives more information than the other api's such as file create time, size, last write time etc.. :)
Those return the same info as GetFileAttributesEx. And I guess there's more overhead to them.

PBrennick

I agree, GetFileAttributesEx is the best way to go and is the only way I do it. After all, it was designed to do just that. The other APIs add the feature but it is not central to the purpose of those APIs.

Paul
The GeneSys Project is available from:
The Repository or My crappy website

jj2007

#10
Quote from: PBrennick on February 21, 2010, 01:22:32 PM
I agree, GetFileAttributesEx is the best way to go and is the only way I do it. After all, it was designed to do just that. The other APIs add the feature but it is not central to the purpose of those APIs.

Paul


It seems Paul is right:
217157  cycles for 3*FindFirstFile
57595   cycles for 3*GetFileAttributesEx
679499  cycles for 3*GetFileSize


EDIT: The GetFileAttributesEx is relatively short...
GetFileLen2 proc fname
LOCAL wfad:WIN32_FILE_ATTRIBUTE_DATA
  call ClearLocVars
  push ebx
  lea ebx, wfad
  GetFileExInfoStandard = 0
  invoke GetFileAttributesEx, fname, GetFileExInfoStandard, ebx
  dec eax ; GfaEx returns zero for an error, but that collides with zero being a valid length
  .if !Sign?
mov eax, [ebx.WIN32_FILE_ATTRIBUTE_DATA.nFileSizeLow]
mov edx, [ebx.WIN32_FILE_ATTRIBUTE_DATA.nFileSizeHigh]
  .endif
  pop ebx
  ret
GetFileLen2 endp


... but has two drawbacks:

First, you must invent your own error handling. The API call returns zero if an error occurs, but a file with zero length is pretty common. I chose above a dec eax, short and clear: eax==-1 means an error. Except for the case of a 4294967295 bytes file...
You can even eliminate that last bit of ambiguity by testing for the sign flag:
invoke GetFileLen2, offset FileA
.if Sign?
MsgBox 0, "An error", "Hi", MB_OK
.endif

Second, GetFileExInfoStandard is zero but there is no guarantee that it stays that way (I bet it will but...):
fInfoLevelId [in]
    A class of attribute information to retrieve.
    This parameter can be the following value from the GET_FILEEX_INFO_LEVELS enumeration.
    Value Meaning
    GetFileExInfoStandard
    The lpFileInformation parameter is a WIN32_FILE_ATTRIBUTE_DATA structure.


Common sense indicates "put a zero", but MS has deliberately chosen to deliver hilariously obscure documentation.

dedndave

but - uh oh - my file sizes don't match yours, Jochen

148082 is incorrect (GetFileLen1 A)

that is for masm32.lib   :eek
my lib file is 148082 bytes

jj2007

Quote from: dedndave on February 22, 2010, 12:34:59 AM
but - uh oh - my file sizes don't match yours, Jochen

That's why I put the equates, Dave :green

BlackVortex

#13
I made a little goasm example proggy, just run it, select the file you want and it will show the bytesize (only works up to 4gb files)

#dynamiclinkfile kernel32.dll user32.dll comdlg32.dll
#include windows.h

DATA SECTION

sz_ProgramTitle    db "Sizer",0
sz_1               db "File size is %lu bytes !",0
sz_Titlestring     db "Select file to get filesize",0
sz_Error           db "Error",0
sz_apifailed       db "Couldn't get info from file",0
h_console_out      dd 0
namebuffer         db 128 dup 0
buffer             db 128 dup 0
ofn   OPENFILENAME <>
fad WIN32_FILE_ATTRIBUTE_DATA <>

CODE SECTION
START:

invoke GetStdHandle, STD_OUTPUT_HANDLE
mov [h_console_out], eax

mov D[ofn.lStructSize],SIZEOF ofn
mov D[ofn.lpstrFile], OFFSET namebuffer
mov D[ofn.nMaxFile], SIZEOF namebuffer
mov D[ofn.lpstrTitle] , addr sz_Titlestring
mov D[ofn.Flags], OFN_FILEMUSTEXIST + OFN_PATHMUSTEXIST + OFN_EXPLORER + OFN_HIDEREADONLY + OFN_NOCHANGEDIR
invoke GetOpenFileName , addr ofn
test eax,eax
jnz > @@
invoke ExitProcess, 0DEADh
@@:

invoke GetFileAttributesEx, addr namebuffer, GetFileExInfoStandard, addr fad
test eax,eax
jnz > @1
invoke MessageBox, NULL, addr sz_apifailed, addr sz_Error, MB_OK + MB_ICONWARNING
invoke ExitProcess, 0ACDCh

@1:
mov eax, [fad.nFileSizeLow]
invoke wsprintf , addr buffer, addr sz_1, eax
invoke MessageBox, NULL, addr buffer, addr sz_ProgramTitle, MB_OK

invoke ExitProcess, NULL

No commenting needed, first paragraph gets the full pathname, second gets the size and then I show it in a MsgBox. I'll attach a compiled binary for testing.

EDIT: Just noticed that uneeded extra command mov eax, ... that was for easier debugging, nvm.

dedndave

i see the equates   :bg
but - i am wondering why the masm32.lib file sizes are different