⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 获得一个目录下的文件名 .txt

📁 会变语言实现的一些程序
💻 TXT
字号:
获得一个目录下的文件名 
    作者: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

--------------------------------------------------------------------------------
<<<上一篇  欢迎访问AoGo汇编小站:http://www.aogosoft.com 下一篇>>>  

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -