?? 獲得一個目錄下的文件名 .txt
字號:
獲得一個目錄下的文件名
作者:LooL 于2007-10-15上傳
--------------------------------------------------------------------------------
要獲得一個目錄下的全部文件名,通常使用 FindFirstFile 和 FindNextFile 這兩個API。具體的做法可想而知:先用前者找到一下,然后再用后者找下一個直到找不到… …除此之外,還有通過DOS命令DIR獲得指定目錄下的目錄列表,然后一個個的拆出來的方法,這種方法過于麻煩,今天要實現(xiàn)的是使用API的 ^_^
先對這些API做個簡單的介紹:
FindFirstFile Function
Searches a directory for a file or subdirectory with a name that matches a specific name.
To specify additional attributes to use in a search, use the FindFirstFileEx function.
To perform this operation as a transacted operation, use the FindFirstFileTransacted function.
HANDLE WINAPI FindFirstFile(
__in LPCTSTR lpFileName,
__out LPWIN32_FIND_DATA lpFindFileData
);
Parameters
lpFileName 指向一個字符串,代表要尋找的文件名。
The directory or path, and the file name, which can include wildcard characters, for example, an asterisk (*) or a question mark (?).
If the string ends with a wildcard, period (.), or directory name, the user must have access to the root and all subdirectories on the path.
lpFindFileData 指向一個緩沖區(qū),函數(shù)會在緩沖區(qū)中返回一個WIN32_FIND_DATA結(jié)構(gòu)
A pointer to the WIN32_FIND_DATA structure that receives information about a found file or subdirectory.
Return Value
If the function succeeds, the return value is a search handle used in a subsequent call to FindNextFile or FindClose.
如果成功,會返回一個handle 可以給FindNextFile或者 FindClose使用
If the function fails, the return value is INVALID_HANDLE_VALUE. To get extended error information, call GetLastError.
如果失敗,返回INVALID_HANDLE_VALUE。
WIN32_FIND_DATA Structure
Contains information about the file that is found by the FindFirstFile, FindFirstFileEx, or FindNextFile function.
typedef struct _WIN32_FIND_DATA {
DWORD dwFileAttributes; 找到的文件的屬性
FILETIME ftCreationTime; 創(chuàng)建日期
FILETIME ftLastAccessTime;最后訪問日期
FILETIME ftLastWriteTime; 最后寫入日期
DWORD nFileSizeHigh; 文件長度的高32位
DWORD nFileSizeLow; 文件長度的低32位
DWORD dwReserved0; 擴展的文件標記
DWORD dwReserved1; 保留
TCHAR cFileName[MAX_PATH];本次找到的文件名
TCHAR cAlternateFileName[14]; 文件的8.3文件名
} WIN32_FIND_DATA,
*PWIN32_FIND_DATA,
*LPWIN32_FIND_DATA;
其中,文件的大小計算方法: (nFileSizeHigh * (MAXDWORD+1)) + nFileSizeLow.
DWORD dwReserved0; 擴展的文件標記,之前一直定義為未使用,而在目前的MSDN上說明為"If the dwFileAttributes member includes the FILE_ATTRIBUTE_REPARSE_POINT attribute, this member specifies the reparse point tag."看起來好像是能否返回文件的所屬類型。
cFileName 中只有文件名稱,不包括路徑。
FindNextFile Function
Continues a file search from a previous call to the FindFirstFile or FindFirstFileEx function.
BOOL WINAPI FindNextFile(
__in HANDLE hFindFile,
__out LPWIN32_FIND_DATA lpFindFileData
);
Parameters
hFindFile FindFirstFile或者FindFirstFileEx返回的handle
The search handle returned by a previous call to the FindFirstFile or FindFirstFileEx function.
lpFindFileData 和FindFirstFile的一樣,用來返回找到的文件信息
A pointer to the WIN32_FIND_DATA structure that receives information about the found file or subdirectory.
The structure can be used in subsequent calls to FindNextFile to indicate from which file to continue the search.
Return Value
If the function succeeds, the return value is nonzero.
If the function fails, the return value is zero (0). To get extended error information, call GetLastError.
If no matching files can be found, the GetLastError function returns ERROR_NO_MORE_FILES.
;#Mode=CON
.386
.model flat, stdcall
option casemap :none
include windows.inc
include user32.inc
include kernel32.inc
include masm32.inc
includelib user32.lib
includelib kernel32.lib
includelib masm32.lib
include macro.asm
.data
szStartPath db 'c:\windows',0
szFilter db '*.exe',0
szEnter db 10,13,0
.data?
buffer db 100 dup(?)
dwCounter dd ?
.CODE
ProcessFile proc
ret
ProcessFile Endp
FindFile proc lpszPath
local stFindFile:WIN32_FIND_DATA
local hFindFile
;MAX_PATH在Windows.inc中有定義=260,注意大小寫
local szPath[MAX_PATH] :byte ;當前要搜索的路徑
local szSearch[MAX_PATH] :byte ;當前要搜索的路徑\*.dll
local szFindFile[MAX_PATH]:byte ;路徑\找到的文件
pushad
invoke lstrcpy,addr szPath,lpszPath ;生成當前要搜索的路徑
@@:
invoke lstrlen,addr szPath
lea esi,szPath
add esi,eax ;指向 szPath 中最后一個字符
xor eax,eax
mov al,'\'
.if BYTE ptr [esi-1] != al ;判斷最后一個字符的前一個字符是否為 \
mov word ptr [esi],ax ;不是,補全 szPath的形式就是 db 'xxxx\',0
.endif
invoke lstrcpy,addr szSearch,addr szPath ;復(fù)制到 szSearch
invoke lstrcat,addr szSearch,addr szFilter ;szSearch 的形式就是 db 'xxxx\*.dll',0
invoke FindFirstFile,addr szSearch,addr stFindFile
.if eax != INVALID_HANDLE_VALUE
mov hFindFile,eax ;保存查找的handle
.repeat
invoke lstrcpy,addr szFindFile,addr szPath ;因為找到的文件是不帶路徑
;所以,結(jié)果上要補全路徑
invoke lstrcat,addr szFindFile,addr stFindFile.cFileName ;加上找到的文件名
.if stFindFile.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY
;找到的是目錄
.if stFindFile.cFileName != '.' ;如果找到的目錄不是"."
invoke FindFile,addr szFindFile ;遞歸,進入這個目錄
.endif
.else ;找到的不是目錄,就是文件
inc dwCounter ;文件計數(shù)器加一
invoke StdOut,addr szFindFile ;輸出文件名
invoke StdOut,addr szEnter
.endif
;繼續(xù)在這個目錄中查找
invoke FindNextFile,hFindFile,addr stFindFile .until (eax==FALSE) ;直到找不到滿足條件的文件
invoke FindClose,hFindFile
.endif
popad
ret
FindFile endp
START:
mov dwCounter,0
invoke FindFile,addr szStartPath ;起始路徑
invoke wsprintf,addr buffer,CTXT("%s %d %s"),CTXT('一共找到'),dwCounter,CTXT('個文件')
invoke StdOut,addr buffer
;暫停顯示,回車鍵關(guān)閉
invoke StdIn,addr buffer,sizeof buffer
invoke ExitProcess,0
end START
(編輯注:這段程序上的排版有些問題,建議讀者拷貝到MasmPlus中查看,根據(jù)自動的邏輯劃分體式可以很清晰的看懂結(jié)構(gòu))
上面的程序參考了《Windows環(huán)境下32位匯編語言程序設(shè)計》,其中的核心部分
invoke FindFirstFile,addr szSearch,addr stFindFile
.if eax != INVALID_HANDLE_VALUE
mov hFindFile,eax ;保存查找的handle
.repeat
invoke lstrcpy,addr szFindFile,addr szPath ;因為找到的文件是不帶路徑
;所以,結(jié)果上要補全路徑
invoke lstrcat,addr szFindFile,addr stFindFile.cFileName ;加上找到的文件名
.if stFindFile.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ;找到的是目錄
.if stFindFile.cFileName != '.' ;如果找到的目錄不是"."
invoke FindFile,addr szFindFile ;遞歸,進入這個目錄
.endif
.else ;找到的不是目錄,就是文件
inc dwCounter ;文件計數(shù)器加一
invoke StdOut,addr szFindFile ;輸出文件名
invoke StdOut,addr szEnter
.endif
;繼續(xù)在這個目錄中查找
invoke FindNextFile,hFindFile,addr stFindFile .until (eax==FALSE) ;直到找不到滿足條件的文件
使用了遞歸,注意這個地方:
.if stFindFile.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY
用來判斷找到的是否為目錄,如果是,則進入遞歸,如果不是,則在下面按照文件的方式處理。但是這里面包含了一個小小的問題:如果我的目錄名稱滿足通配符,會找到,但是因為它不是文件,可能會被漏掉。
舉例說明,我在Windows目錄下使用md lll.exe 建立一個名稱為 "lll.exe"的目錄。使用dir *.exe命令,結(jié)果如下:
而使用我們的程序,結(jié)果卻是:
解決方法是
.if stFindFile.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ;找到的是目錄?
.if stFindFile.cFileName != '.' ;如果找到的目錄不是"."
****在這個地方或者下一跳代碼的后面進行處理
invoke FindFile,addr szFindFile ;遞歸,進入這個目錄
.endif
.else ;找到的不是目錄,就是文件
...
.endif
另外,試驗中發(fā)現(xiàn):如果你使用非 "*.*"的通配符查找,是無法找到目錄的。意思是如果你打算用這種方法"查找給定的路徑下面的包括子目錄的所有滿足條件的文件",是不行的。
收稿 2007-10-12
--------------------------------------------------------------------------------
<<<上一篇 歡迎訪問AoGo匯編小站:http://www.aogosoft.com 下一篇>>>
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -