Possible new FileListToArray method for AutoIt
Posted: Sun Apr 08, 2012 11:08 am
Got the following from Onepiece via BP -- with some slight modifications from me. It does seem faster, so later I'll do some comparative timings with SetupS between the two methods. If it's significantly faster -- the claims are as high as 20% -- then I'll adapt it to SetupS (v8 & v9).
Code: Select all
#include <Constants.au3>
#include <File.au3>
#include <Array.au3>
#include <Date.au3>
Local $StopWatch
;Test original _FileListToArray
Timer($StopWatch) ; start timer
Local $aFileList = _FileListToArray(@WindowsDir, '*.*')
Timer($StopWatch, 'Using original _FileListToArray', True) ; stop timer
;Test _FileListToArrayPlus
Timer($StopWatch) ; start timer
Local $bFileList = _FileListToArrayPlus(@WindowsDir, '*.*')
Timer($StopWatch, 'Using _FileListToArrayPlus', True) ; stop timer
_ArrayDisplay($aFileList, 'From original _FileListToArray')
_ArrayDisplay($bFileList, 'From _FileListToArrayPlus')
Exit
Func _FileListToArrayPlus($sPath, $sFilter = '', $iFlag = 0, $sOrder = '')
; ================================================================
; (Conceptual replacement for _FileListToArray)
;
; Description .....
; Lists files and\or folders in a specified path (actually uses Dir /B)
;
; Syntax ..........
; _FileListToArrayPlus($sPath[, $sFilter = ''[, $iFlag = 0[, $sOrder = 0]]])
;
; Parameters ......
; $sPath - Path to generate filelist for.
; $sFilter - Optional the filter to use (same syntax as DIR).
; $iFlag - Optional: specifies results to return (add values to combine).
; |0 Return both files and folders (Default)
; |1 Return files only
; |2 Return Folders only
; |4 Return full-path
; |8 Recurse sub-folders
; $sOrder - Optional: specifies how to sort returned files/folders.
; N By name (alphabetic) S By size (smallest first)
; E By extension (alphabetic) D By date/time (oldest first)
; G Group directories first - Prefix to reverse order
; eg. "GN" for folders first then alphabetically by name
;
; Return values ...
; One-dimensional array made up as follows:
; $array[0] = Number of Files\Folders returned
; $array[1] = 1st File\Folder
; $array[2] = 2nd File\Folder
; $array[3] = 3rd File\Folder
; $array[n] = nth File\Folder
;
; @Error -
; |1 = Path not found or invalid
; |2 = Invalid $sFilter
; ================================================================
Local $i, $foo, $Line, $aFileList, $sRecurse, $sAttrib = '/a'
$sPath = NoBackslash(StringRegExpReplace($sPath, '[\\/]+\z', ''))
If Not FileExists($sPath) Then Return SetError(1, 1, '')
If StringRegExp($sFilter, '[\\/:><\|]|(?s)\A\s*\z') Then Return SetError(2, 2, '')
If $sFilter = '*' Or $sFilter = '*.*' Then $sFilter = ''
If $sFilter <> '' Then $sFilter = '\' & $sFilter
If Not (BitAND($iFlag, 1) = 1 And BitAND($iFlag, 2) = 2) Then ; in case $iFlag is 3, 7, 11, or 15 (assumes both files and folders)
If BitAND($iFlag, 1) = 1 Then $sAttrib &= '-D' ;files only
If BitAND($iFlag, 2) = 2 Then $sAttrib &= 'D' ;folders only
EndIf
If BitAND($iFlag, 8) = 8 Then $sRecurse &= '/s' ;recurse
$sOrder = StringReplace(StringReplace($sOrder, '/o:', ''), '/o', '')
If $sOrder <> '' Then $sOrder = '/o' & $sOrder
$foo = Run(@ComSpec & ' /c DIR "' & $sPath & $sFilter & '" /b' & $sAttrib & $sRecurse & $sOrder, '', @SW_HIDE, $STDOUT_CHILD)
Do
$Line &= StdoutRead($foo)
Until @error
$aFileList = StringSplit(StringLeft($Line, StringLen($Line) - 2), @CRLF, 1)
If @error = 1 Then
ReDim $aFileList[1]
$aFileList[0] = 0
ElseIf BitAND($iFlag, 8) <> 8 And BitAND($iFlag, 4) = 4 Then ; add full-path
For $i = 1 To $aFileList[0]
$aFileList[$i] = $sPath & '\' & $aFileList[$i]
Next
EndIf
Return $aFileList
EndFunc
Func Timer(ByRef $Timer, $Message = '', $ShowTicks = False)
; ===================================================
; Parameters ....
; $Timer - The timer object to use.
; $Message - Optional: leave empty to only (re)start $Timer
; $ShowTicks - Optional: True to not convert to HH:MM:SS format
;
; Example of use:
; Timer($StopWatch) ; start timer
; Timer($StopWatch, "Post-processing done!", True) ; stop timer
; ===================================================
Local $Secs, $Mins, $Hour, $Time = Int(TimerDiff($Timer))
If Not $ShowTicks Then
_TicksToTime($Time, $Hour, $Mins, $Secs)
$Time = StringFormat('%02i:%02i:%02i', $Hour, $Mins, $Secs)
EndIf
If $Message <> '' Then MsgBox(262144, $Message, $Time)
$Timer = TimerInit()
EndFunc ;==>Timer