The MASM Forum Archive 2004 to 2012

General Forums => The Workshop => Topic started by: Astro on February 20, 2010, 05:27:52 PM

Title: Best way to determine file length??
Post by: Astro on February 20, 2010, 05:27:52 PM
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.
Title: Re: Best way to determine file length??
Post by: BlackVortex on February 20, 2010, 05:39:12 PM
GetFileSizeEx  ?
http://msdn.microsoft.com/en-us/library/aa364957%28VS.85%29.aspx

:P
Title: Re: Best way to determine file length??
Post by: Astro on February 20, 2010, 05:56:44 PM
 :thumbu

Best regards,
Robin.
Title: Re: Best way to determine file length??
Post by: Astro on February 20, 2010, 06:19:15 PM
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.
Title: Re: Best way to determine file length??
Post by: dedndave on February 20, 2010, 07:01:57 PM
the first "print" probably destroys the contents of EDX

push edx
print.....
pop edx
print....
Title: Re: Best way to determine file length??
Post by: jj2007 on February 20, 2010, 10:53:53 PM
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
Title: Re: Best way to determine file length??
Post by: BlackVortex on February 21, 2010, 04:28:00 AM
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.
Title: Re: Best way to determine file length??
Post by: 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.. :)
Title: Re: Best way to determine file length??
Post by: BlackVortex on February 21, 2010, 01:04:45 PM
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.
Title: Re: Best way to determine file length??
Post by: 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
Title: Re: Best way to determine file length??
Post by: jj2007 on February 21, 2010, 05:32:14 PM
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  (http://msdn.microsoft.com/en-us/library/aa364946%28VS.85%29.aspx)[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.
Title: Re: Best way to determine file length??
Post by: dedndave on February 22, 2010, 12:34:59 AM
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
Title: Re: Best way to determine file length??
Post by: jj2007 on February 22, 2010, 07:34:54 AM
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
Title: Re: Best way to determine file length??
Post by: BlackVortex on February 22, 2010, 09:56:09 AM
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.
Title: Re: Best way to determine file length??
Post by: dedndave on February 22, 2010, 11:15:40 AM
i see the equates   :bg
but - i am wondering why the masm32.lib file sizes are different
Title: Re: Best way to determine file length??
Post by: jj2007 on February 22, 2010, 11:28:20 AM
Quote from: dedndave on February 22, 2010, 11:15:40 AM
i see the equates   :bg
but - i am wondering why the masm32.lib file sizes are different
My other puter says masm32.lib = 148082 of 22.4.09
Maybe one day Hutch will add a readme.txt containing the word "version" ;-)
Title: Re: Best way to determine file length??
Post by: dedndave on February 22, 2010, 11:39:36 AM
oh - ok - we are the same
the value you have in the equate is 148076