April 26, 2024, 11:09:28 PM

News:

IonicWind Snippit Manager 2.xx Released!  Install it on a memory stick and take it with you!  With or without IWBasic!


Processing Files and Subdirectories

Started by billhsln, December 18, 2010, 11:34:51 PM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

billhsln

I have created a program to test how long it takes to process lots of file info.  This program goes thru the standard IWBasic FINDOPEN/FINDNEXT/FINDCLOSE method along with getting the files size.  This took almost 9 minutes to process my WINDOWS directory.  To do it with the FindFirstFileA/FindNextFileA/WIN32FindClose and still get the total file size only took 2 seconds.  This could also be modified to get the dates/times of the files.  If you need to know file size or dates of the files, I would use the FindFirstFileA/FindNextFileA/WIN32FindClose method, because it is very fast.  But if all you need is basic info the IWBasic FINDOPEN/FINDNEXT/FINDCLOSE method is just as fast.

$MAIN
AUTODEFINE "off"

INT hrs
INT max1 = 0, maxd1 = 0, cd1 = 0, td1 = 0, fls1 = 0
INT max2 = 0, maxd2 = 0, cd2 = 0, td2 = 0, fls2 = 0
UINT64 tFileSize1 = 0, tFileSize2 = 0
UINT handle
STRING filename
STRING BeginTime1, EndTime1
STRING BeginTime2, EndTime2
STRING fDate, temp, fTime, To_Date

DECLARE IMPORT,GetFileSize(hfile:UINT, lpfilesizehigh:UINT BYREF), UINT
'the neccessary windows functions
DECLARE IMPORT,CreateFileA(name:STRING,access:INT,share:INT,security:INT,create:INT,flags:INT,handle:INT), INT
DECLARE IMPORT,CloseHandle(handle:INT), INT

DECLARE IMPORT,GetFileTime(handle:INT,creation:filetime,access:filetime,writet:filetime), INT
DECLARE IMPORT,FileTimeToSystemTime(timef:filetime,times:systemtime), INT
DECLARE IMPORT,FileTimeToLocalFileTime(timef:filetime, timel:filetime)

DECLARE "kernel32",FindFirstFileA(name:STRING,pfd:WIN32_FIND_DATA), UINT
DECLARE "kernel32",FindNextFileA(handle:UINT,pfd:WIN32_FIND_DATA), UINT
DECLARE "kernel32",WIN32FindClose ALIAS FindClose(handle:UINT), INT

CONST MAX_PATH = 261

'all files store the date/times in
TYPE filetime
DEF qwtime:UINT64
ENDTYPE

TYPE systemtime,2
DEF wMillisecondsec,wSecond,wMinute,wHour,wDay,wDayofWeek,wMonth,wYear:WORD
ENDTYPE

TYPE WIN32_FIND_DATA
DEF dwFileAttributes AS INT
DEF ftCreationTime AS FILETIME
DEF ftLastAccessTime AS FILETIME
DEF ftLastWriteTime AS FILETIME
DEF nFileSizeHigh AS UINT
DEF nFileSizeLow AS UINT
DEF dwReserved0 AS INT
DEF dwReserved1 AS INT
DEF cFileName[MAX_PATH] AS ISTRING
DEF cAlternate[14] AS ISTRING
ENDTYPE

'some useful values
SETID "OPENEXISTING",3
SETID "GENERICREAD",0x80000000

filename = "C:\\Windows\\"

BeginTime1 = TIME$
GetFiles1(filename)
EndTime1 = TIME$

BeginTime2 = TIME$
GetFiles2(filename)
EndTime2 = TIME$

' max? = longest length of path and filename
' maxd? = maximum number of directory levels
' td? = total number of directories
' tFileSize? = Total file size
' fls? = Number of files

PRINT max1, " ", maxd1, " ", tFileSize1, " ", fls1, " ", td1
PRINT "Begin ", BeginTime1, " ", EndTime1
PRINT " "
PRINT max2, " ", maxd2, " ", tFileSize2, " ", fls2, " ", td2
PRINT "Begin ", BeginTime2, " ", EndTime2,

INPUT max1
END

SUB GetFiles1(path:STRING)
DEF dir, attrib = 0, r:INT
DEF hfile, sizehigh = 0, filesize:UINT
DEF filename = "":STRING
DEF creation, access, writet, temptime:filetime
DEF times:systemtime

IF cd1 > maxd1 THEN maxd1 = cd1

IF cd1 = 1 THEN PRINT path

dir = FINDOPEN(path + "*.*")
IF (dir)
DO
filename = FINDNEXT(dir,attrib)
IF len(filename)
IF (attrib & @file_directory)
IF (filename = ".") OR (filename = "..")
r = 0
ELSE
td1++
cd1++
GetFiles1(path + filename + "\\")
ENDIF
ELSE
fls1++
hfile = createfilea(path + filename,@genericread,0,0,@openexisting,0,0)
IF (hfile > 0)
filesize = GetFileSize(hfile, sizehigh)
' if (GetFileTime(hfile,creation,access,writet))
' FileTimeToLocalFileTime(writet,temptime)
' filetimetosystemtime(temptime,times)
' fDate = ltrim$(str$(times.wYear)) + "-"
' temp = ltrim$(str$(times.wMonth))
' if (len(temp) < 2) then temp = "0" + temp
' fDate += temp + "-"
' temp = ltrim$(str$(times.wDay))
' if (len(temp) < 2) then temp = "0" + temp
' fDate += temp
' hrs = times.wHour
' temp = ltrim$(str$(hrs))
' if (len(temp) < 2) then temp = "0" + temp
' fTime = temp + ":"
' temp = ltrim$(str$(times.wMinute))
' if (len(temp) < 2) then temp = "0" + temp
' fTime += temp
' To_Date = fDate + " " + fTime
' endif
endif
closehandle(hfile)
tFileSize1 += ((sizehigh << 32) | filesize)
r = LEN(path) + LEN(filename)
IF r > max1
max1 = r
ENDIF
ENDIF
ENDIF
UNTIL filename = ""
FINDCLOSE dir
ENDIF
cd1--
RETURN
ENDSUB

SUB GetFiles2(path:STRING)
DEF dir, r:INT
DEF hfile:UINT
DEF From_Date:STRING
DEF pfd:WIN32_FIND_DATA
DEF times:systemtime

IF cd2 > maxd2 THEN maxd2 = cd2

IF cd2 = 1 THEN PRINT path

dir = FindFirstFileA(path + "*.*",pfd)
IF (dir)
DO
hfile = FindNextFileA(dir,pfd)
IF hfile > 0
IF (pfd.dwFileAttributes & @file_directory)
IF (pfd.cFileName = ".") OR (pfd.cFileName = "..")
r = 0
ELSE
td2++
cd2++
GetFiles2(path + pfd.cFileName + "\\")
ENDIF
ELSE
fls2++
tFileSize2 += ((pfd.nFileSizeHigh << 32) | pfd.nFileSizeLow)
' filetimetosystemtime(pfd.ftCreationTime,times)
' fDate = ltrim$(str$(times.wYear)) + "-"
' temp = ltrim$(str$(times.wMonth))
' if (len(temp) < 2) then temp = "0" + temp
' fDate += temp + "-"
' temp = ltrim$(str$(times.wDay))
' if (len(temp) < 2) then temp = "0" + temp
' fDate += temp
' hrs = times.wHour
' temp = ltrim$(str$(hrs))
' if (len(temp) < 2) then temp = "0" + temp
' fTime = temp + ":"
' temp = ltrim$(str$(times.wMinute))
' if (len(temp) < 2) then temp = "0" + temp
' fTime += temp
' From_Date = fDate + " " + fTime
' PRINT From_Date
r = LEN(path) + LEN(pfd.cFileName)
IF r > max2
max2 = r
ENDIF
ENDIF
ENDIF
UNTIL hfile < 1
WIN32FindClose(dir)
ENDIF
cd2--
RETURN
ENDSUB

SUB GetFiles3(path:STRING)
INT dir, r
UINT hfile
DEF pfd:WIN32_FIND_DATA

IF cd2 > maxd2 THEN maxd2 = cd2

IF cd2 = 1 THEN PRINT path

dir = FindFirstFileA(path + "*.*",pfd)
IF (dir)
DO
hfile = FindNextFileA(dir,pfd)
IF hfile > 0
IF (pfd.dwFileAttributes & @file_hidden) OR (pfd.dwFileAttributes & @file_system)
r = 0
ELSE
IF (pfd.dwFileAttributes & @file_directory)
IF (pfd.cFileName = ".") OR (pfd.cFileName = "..")
r = 0
ELSE
td2++
cd2++
GetFiles3(path + pfd.cFileName + "\\")
ENDIF
ELSE
fls2++
tFileSize2 += ((pfd.nFileSizeHigh << 32) | pfd.nFileSizeLow)
r = LEN(path) + LEN(pfd.cFileName)
IF r > max2
max2 = r
ENDIF
ENDIF
ENDIF
ENDIF
UNTIL hfile < 1
WIN32FindClose(dir)
ENDIF
cd2--
RETURN
ENDSUB


Info from Properties:
16.5 GB (17,718,797,319 bytes)
72,237 Files, 15,095 Folders

Values returned on my PC:

222  8  18160505890  70607  15069
Begin 23:40:22 23:49:11

222  8  17189128538  70607  15069
Begin 23:49:11 23:49:13

The program is set to start at C:\WINDOWS, but can also be done to start at C:\.

The only problem I have is that the counts do not always match for either file size or number of files and subdirectorys.  It does match on smaller subdirectories, but on large ones, like C:\WINDOWS or C:\USER the file size/counts/subdirs do not match 100% of the time.  Not sure why.....

Hope that someone will find this of some use.

Bill
When all else fails, get a bigger hammer.

sapero

December 20, 2010, 02:06:07 PM #1 Last Edit: December 25, 2010, 08:51:36 AM by sapero
I have a tip:

Just cast the pointer( returned from FINDOPEN) to WIN32_FIND_DATA, to access the fields:

UINT pFind = FINDOPEN("C:\\ADC51\\*.*")

while (pFind)
int64 size = *<WIN32_FIND_DATA>pFind.nFileSizeLow + 4294967296q * *<WIN32_FIND_DATA>pFind.nFileSizeHigh
print USING("############# ",size), "\t",

if (*<WIN32_FIND_DATA>pFind.dwFileAttributes & 0x00000010)
print "[",*<WIN32_FIND_DATA>pFind.cFileName,"]"
else
print *<WIN32_FIND_DATA>pFind.cFileName
endif

istring temp[MAX_PATH] = FINDNEXT(pFind)
if (!*<WIN32_FIND_DATA>pFind.cFileName[0])
FINDCLOSE(pFind)
pFind = 0
endif
wend


And a small note: MAX_PATH should be 260.

billhsln

It seems that under IWB 2.0, this statement no longer works as expected:

if (!*<WIN32_FIND_DATA>pFind.cFileName[0])

I had to change it to:

if (*<WIN32_FIND_DATA>pFind.cFileName[0] = "")

To make it work right.

Bill
When all else fails, get a bigger hammer.