主题:[原创]非递归法遍历文件
最近写directfilemanager中的一个扩展程序需要扫描磁盘文件,调用常见的递归方式遍历文件,结果堆栈溢出,于是写了个非递归的遍历文件函数,性能还要好些,分享下:
Option Explicit
Option Base 0
Private Declare Function FindFirstFile Lib "kernel32" Alias "FindFirstFileA" (ByVal lpFileName As String, lpFindFileData As WIN32_FIND_DATA) As Long
Private Declare Function FindNextFile Lib "kernel32" Alias "FindNextFileA" (ByVal hFindFile As Long, lpFindFileData As WIN32_FIND_DATA) As Long
Private Declare Function GetFileAttributes Lib "kernel32" Alias "GetFileAttributesA" (ByVal lpFileName As String) As Long
Private Declare Function FindClose Lib "kernel32" (ByVal hFindFile As Long) As Long
Private Const MAX_PATH = 260
Private Const MAXDWORD = &HFFFF
Private Const INVALID_HANDLE_VALUE = -1
Private Const FILE_ATTRIBUTE_ARCHIVE = &H20
Private Const FILE_ATTRIBUTE_DIRECTORY = &H10
Private Const FILE_ATTRIBUTE_HIDDEN = &H2
Private Const FILE_ATTRIBUTE_NORMAL = &H80
Private Const FILE_ATTRIBUTE_READONLY = &H1
Private Const FILE_ATTRIBUTE_SYSTEM = &H4
Private Const FILE_ATTRIBUTE_TEMPORARY = &H100
Private Type FILETIME
dwLowDateTime As Long
dwHighDateTime As Long
End Type
Private Type WIN32_FIND_DATA
dwFileAttributes As Long
ftCreationTime As FILETIME
ftLastAccessTime As FILETIME
ftLastWriteTime As FILETIME
nFileSizeHigh As Long
nFileSizeLow As Long
dwReserved0 As Long
dwReserved1 As Long
cFileName As String * MAX_PATH
cAlternate As String * 14
End Type
Private Function StripNulls(OriginalStr As String) As String
If (InStr(OriginalStr, Chr(0)) > 0) Then
OriginalStr = Left(OriginalStr, InStr(OriginalStr, Chr(0)) - 1)
End If
StripNulls = OriginalStr
End Function
Public Function SearchFiles(ByVal SearchPath As String, GetFilePathName() As String) As Long
Dim hSearch As Long
Dim WFD As WIN32_FIND_DATA
Dim curF As Long
Dim curPath As String
Dim CountAll As Long
Dim NextSearch As Long
Dim FileName As String
ReDim GetFilePathName(0)
GetFilePathName(0) = IIf(Right(SearchPath, 1) = "\", Left(SearchPath, Len(SearchPath) - 1), SearchPath)
Do
curPath = GetFilePathName(curF)
If GetFileAttributes(curPath) And FILE_ATTRIBUTE_DIRECTORY Then
curPath = curPath & "\*"
hSearch = FindFirstFile(curPath, WFD)
If hSearch <> INVALID_HANDLE_VALUE Then
Do
FileName = StripNulls(WFD.cFileName)
If (FileName <> ".") And (FileName <> "..") Then
CountAll = CountAll + 1
ReDim Preserve GetFilePathName(CountAll)
GetFilePathName(CountAll) = GetFilePathName(curF) & "\" & FileName
End If
NextSearch = FindNextFile(hSearch, WFD)
Loop While NextSearch > 0
End If
Call FindClose(hSearch)
End If
curF = curF + 1
Loop While curF <= CountAll
SearchFiles = CountAll
End Function
Option Explicit
Option Base 0
Private Declare Function FindFirstFile Lib "kernel32" Alias "FindFirstFileA" (ByVal lpFileName As String, lpFindFileData As WIN32_FIND_DATA) As Long
Private Declare Function FindNextFile Lib "kernel32" Alias "FindNextFileA" (ByVal hFindFile As Long, lpFindFileData As WIN32_FIND_DATA) As Long
Private Declare Function GetFileAttributes Lib "kernel32" Alias "GetFileAttributesA" (ByVal lpFileName As String) As Long
Private Declare Function FindClose Lib "kernel32" (ByVal hFindFile As Long) As Long
Private Const MAX_PATH = 260
Private Const MAXDWORD = &HFFFF
Private Const INVALID_HANDLE_VALUE = -1
Private Const FILE_ATTRIBUTE_ARCHIVE = &H20
Private Const FILE_ATTRIBUTE_DIRECTORY = &H10
Private Const FILE_ATTRIBUTE_HIDDEN = &H2
Private Const FILE_ATTRIBUTE_NORMAL = &H80
Private Const FILE_ATTRIBUTE_READONLY = &H1
Private Const FILE_ATTRIBUTE_SYSTEM = &H4
Private Const FILE_ATTRIBUTE_TEMPORARY = &H100
Private Type FILETIME
dwLowDateTime As Long
dwHighDateTime As Long
End Type
Private Type WIN32_FIND_DATA
dwFileAttributes As Long
ftCreationTime As FILETIME
ftLastAccessTime As FILETIME
ftLastWriteTime As FILETIME
nFileSizeHigh As Long
nFileSizeLow As Long
dwReserved0 As Long
dwReserved1 As Long
cFileName As String * MAX_PATH
cAlternate As String * 14
End Type
Private Function StripNulls(OriginalStr As String) As String
If (InStr(OriginalStr, Chr(0)) > 0) Then
OriginalStr = Left(OriginalStr, InStr(OriginalStr, Chr(0)) - 1)
End If
StripNulls = OriginalStr
End Function
Public Function SearchFiles(ByVal SearchPath As String, GetFilePathName() As String) As Long
Dim hSearch As Long
Dim WFD As WIN32_FIND_DATA
Dim curF As Long
Dim curPath As String
Dim CountAll As Long
Dim NextSearch As Long
Dim FileName As String
ReDim GetFilePathName(0)
GetFilePathName(0) = IIf(Right(SearchPath, 1) = "\", Left(SearchPath, Len(SearchPath) - 1), SearchPath)
Do
curPath = GetFilePathName(curF)
If GetFileAttributes(curPath) And FILE_ATTRIBUTE_DIRECTORY Then
curPath = curPath & "\*"
hSearch = FindFirstFile(curPath, WFD)
If hSearch <> INVALID_HANDLE_VALUE Then
Do
FileName = StripNulls(WFD.cFileName)
If (FileName <> ".") And (FileName <> "..") Then
CountAll = CountAll + 1
ReDim Preserve GetFilePathName(CountAll)
GetFilePathName(CountAll) = GetFilePathName(curF) & "\" & FileName
End If
NextSearch = FindNextFile(hSearch, WFD)
Loop While NextSearch > 0
End If
Call FindClose(hSearch)
End If
curF = curF + 1
Loop While curF <= CountAll
SearchFiles = CountAll
End Function