会变语言实现的一些程序

源代码在线查看: 获得一个目录下的文件名 .txt

软件大小: 1703 K
上传用户: dedien
关键词: 语言 程序
下载地址: 免注册下载 普通下载 VIP

相关代码

				获得一个目录下的文件名 
				    作者:LooL 于2007-10-15上传   
				
				--------------------------------------------------------------------------------
				   要获得一个目录下的全部文件名,通常使用 FindFirstFile 和 FindNextFile 这两个API。具体的做法可想而知:先用前者找到一下,然后再用后者找下一个直到找不到… …除此之外,还有通过DOS命令DIR获得指定目录下的目录列表,然后一个个的拆出来的方法,这种方法过于麻烦,今天要实现的是使用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 指向一个缓冲区,函数会在缓冲区中返回一个WIN32_FIND_DATA结构
				   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;  创建日期
				     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   ;复制到 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 ;因为找到的文件是不带路径
				                                     ;所以,结果上要补全路径
				      invoke   lstrcat,addr   szFindFile,addr   stFindFile.cFileName  ;加上找到的文件名
				               .if      stFindFile.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY 
				                                    ;找到的是目录
				                  .if   stFindFile.cFileName != '.'         ;如果找到的目录不是"."
				                  invoke FindFile,addr   szFindFile      ;递归,进入这个目录
				               .endif
				               .else      ;找到的不是目录,就是文件
				                  inc    dwCounter               ;文件计数器加一
				                  invoke StdOut,addr   szFindFile      ;输出文件名
				                  invoke StdOut,addr   szEnter
				               .endif
				                  ;继续在这个目录中查找
				                  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
				      
				      ;暂停显示,回车键关闭
				      invoke StdIn,addr buffer,sizeof buffer
				      invoke ExitProcess,0
				      
				   end START
				   
				
				   (编辑注:这段程序上的排版有些问题,建议读者拷贝到MasmPlus中查看,根据自动的逻辑划分体式可以很清晰的看懂结构)
				
				   上面的程序参考了《Windows环境下32位汇编语言程序设计》,其中的核心部分
				
				   
				   invoke   FindFirstFile,addr   szSearch,addr   stFindFile
				   .if      eax != INVALID_HANDLE_VALUE
				         mov   hFindFile,eax                     ;保存查找的handle
				         .repeat
				      invoke   lstrcpy,addr   szFindFile,addr   szPath ;因为找到的文件是不带路径
				                                             ;所以,结果上要补全路径
				   invoke   lstrcat,addr   szFindFile,addr   stFindFile.cFileName  ;加上找到的文件名
				   .if      stFindFile.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY          ;找到的是目录
				      .if   stFindFile.cFileName != '.'         ;如果找到的目录不是"."
				      invoke FindFile,addr   szFindFile      ;递归,进入这个目录
				   .endif
				   .else      ;找到的不是目录,就是文件
				      inc    dwCounter               ;文件计数器加一
				      invoke StdOut,addr   szFindFile      ;输出文件名
				      invoke StdOut,addr   szEnter
				   .endif
				   ;继续在这个目录中查找
				   invoke   FindNextFile,hFindFile,addr   stFindFile              .until   (eax==FALSE)      ;直到找不到满足条件的文件
				   
				
				   使用了递归,注意这个地方:
				   
				   .if      stFindFile.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY  
				   
				
				   用来判断找到的是否为目录,如果是,则进入递归,如果不是,则在下面按照文件的方式处理。但是这里面包含了一个小小的问题:如果我的目录名称满足通配符,会找到,但是因为它不是文件,可能会被漏掉。
				
				   举例说明,我在Windows目录下使用md lll.exe 建立一个名称为 "lll.exe"的目录。使用dir *.exe命令,结果如下:
				   
				
				   而使用我们的程序,结果却是:
				   
				
				   解决方法是
				   
				   .if      stFindFile.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ;找到的是目录?
				      .if   stFindFile.cFileName != '.'         ;如果找到的目录不是"."
				            ****在这个地方或者下一跳代码的后面进行处理
				            invoke FindFile,addr   szFindFile      ;递归,进入这个目录
				      .endif
				   .else      ;找到的不是目录,就是文件
				      ...
				   .endif
				   
				
				   另外,试验中发现:如果你使用非 "*.*"的通配符查找,是无法找到目录的。意思是如果你打算用这种方法"查找给定的路径下面的包括子目录的所有满足条件的文件",是不行的。
				
				   
				
				   收稿 2007-10-12
				
				--------------------------------------------------------------------------------
				  
							

相关资源