zoukankan      html  css  js  c++  java
  • Windows 实战项目 001 文件扫描器 (01)

    ---恢复内容开始---

    # Windows 实战项目 001 文件扫描器 (01)

      - 主要实现功能

        -  搜索系统目录文件

        -  找到文件并打印输出

      - 主要使用到的函数

        - FindFirstFile

         函数原型:

    1             HANDLE WINAPI FindFirstFile(
    2               _In_  LPCTSTR           lpFileName,
    3               _Out_ LPWIN32_FIND_DATA lpFindFileData
    4             );

          参数1 lpFileName

            搜索的文件名

    c:Windows*.*                                //在c:Windows目录中查找所有文件
    c:WindowsSystem32*.dll                    //在c:WindowsSystem32目录中查找所有dll文件
    c:WindowsSystem.ini;                      //在c:Windows目录中查找System.ini文件
    c:Windowsa???.*                           //在c:Windows目录中查找所有以a开头的文件名长度.为4个字符的文件
    Test.dat                                    //在当前目录查找Test.dat文件
    *.*                                         //在当前目录查找所有文件

          参数2 lpFindFileData

            搜索到文件数据 输出信息的 结构体

          

          返回值

            返回成功

              如果函数返回成功,则返回值是后续调用 FindNextFile 或者 FindClose 时使用的搜索句柄,

              lpFindFileData 参数包含有关找到的第一个文件或目录的信息

            返回失败

              如果函数失败或无法从lpFileName参数中的搜索字符串中找到文件,则返回为 INVALID_HANDLE_VALUE

              并且lpFindFileData的内容不确定的,用 GetLastError 获取操作代码

                如果函数失败,因为找不到匹配文件,GetLastError函数返回 ERROR_FILE_NOT_FOUND;

        - FindNextFile

          函数原型

    1       HANDLE WINAPI FindFirstFile(
    2        _In_  LPCTSTR           lpFileName,
    3         _Out_ LPWIN32_FIND_DATA lpFindFileData
    4       );

          参数1:lpFileName

              搜索到的文件名字,或者目录名称。不能为空

          参数2 lpFindFileData

            搜索到文件数据 输出信息的 结构体

          

          返回值

            返回成功

              如果函数返回成功,则返回值是后续调用 FindNextFile 或者 FindClose 时使用的搜索句柄,

              lpFindFileData 参数包含有关找到的第一个文件或目录的信息

            返回失败

              如果函数失败或无法从lpFileName参数中的搜索字符串中找到文件,则返回为 INVALID_HANDLE_VALUE

              并且lpFindFileData的内容不确定的,用 GetLastError 获取操作代码

                如果函数失败,因为找不到匹配文件,GetLastError函数返回 ERROR_FILE_NOT_FOUND;

        

    文件属性常量

    文件属性是文件系统在磁盘上存储的元数据值,由系统使用,可通过各种文件I / O API向开发人员提供。有关相关API和主题的列表,请参阅另请参阅部分。

    恒/值描述
    FILE_ATTRIBUTE_ARCHIVE
    32(0x20)

    作为归档文件或目录的文件或目录。应用程序通常使用此属性来标记文件进行备份或删除。 

    FILE_ATTRIBUTE_COMPRESSED
    2048(0x800)

    被压缩的文件或目录。对于一个文件,文件中的所有数据都被压缩。对于目录,压缩是新创建的文件和子目录的默认值。

    FILE_ATTRIBUTE_DEVICE
    64(0x40)

    此值保留供系统使用。

    FILE_ATTRIBUTE_DIRECTORY
    16(0x10)

    标识目录的句柄。

    FILE_ATTRIBUTE_ENCRYPTED
    16384(0x4000)

    加密的文件或目录。对于一个文件,文件中的所有数据流都被加密。对于目录,加密是新创建的文件和子目录的默认值。

    FILE_ATTRIBUTE_HIDDEN
    2(0x2)

    该文件或目录被隐藏。它不包括在普通目录列表中。

    FILE_ATTRIBUTE_INTEGRITY_STREAM
    32768(0x8000)

    目录或用户数据流配置完整性(仅在ReFS卷上支持)。它不包括在普通目录列表中。如果文件被重命名,则完整性设置将与文件保持一致。如果文件被复制,则如果源文件或目标目录具有完整性集,则目标文件将具有完整性集。

    Windows Server 2008 R2,Windows 7,Windows Server 2008,Windows Vista,Windows Server 2003和Windows XP:   Windows Server 2012之前不支持此标志。

    FILE_ATTRIBUTE_NORMAL
    128(0x80)

    没有设置其他属性的文件。此属性仅在单独使用时有效。

    FILE_ATTRIBUTE_NOT_CONTENT_INDEXED
    8192(0x2000)

    文件或目录不被内容索引服务编入索引。

    FILE_ATTRIBUTE_NO_SCRUB_DATA
    131072(0x20000)

    用户数据流不被背景数据完整性扫描器(AKA scrubber)读取。当设置在目录上时,它只提供继承。此标志仅在存储空间和ReFS卷上受支持。它不包括在普通目录列表中。

    Windows Server 2008 R2,Windows 7,Windows Server 2008,Windows Vista,Windows Server 2003和Windows XP:   Windows 8和Windows Server 2012之前不支持此标志。

    FILE_ATTRIBUTE_OFFLINE
    4096(0x1000)

    文件的数据不可用。该属性表示文件数据被物理移动到离线存储。该属性由分层存储管理软件Remote Storage使用。应用程序不应该随意更改此属性。

    FILE_ATTRIBUTE_READONLY
    1(0x1)

    只读的文件。应用程序可以读取文件,但不能写入或删除它。该属性不符合目录。有关详细信息,

    FILE_ATTRIBUTE_RECALL_ON_DATA_ACCESS
    4194304(0x400000)

    设置此属性时,表示文件或目录在本地不完全存在。对于一个文件,意味着并不是所有的数据都在本地存储上(例如,它可能是稀疏的,还有一些数据仍在远程存储中)。对于目录,这意味着某些目录内容正在从另一个位置进行虚拟化。读取文件/枚举目录将比正常情况更昂贵,例如,将导致至少一些文件/目录内容从远程存储提取。只有内核模式的呼叫者可以设置这个位。

    FILE_ATTRIBUTE_RECALL_ON_OPEN
    262144(0x40000)

    此属性仅显示在目录枚举类(FILE_DIRECTORY_INFORMATION,FILE_BOTH_DIR_INFORMATION等)中。当设置此属性时,表示文件或目录在本地系统上没有物理表示; 该项目是虚拟的。打开该项目将比正常更昂贵,例如,它会导致至少一些从远程商店获取。

    FILE_ATTRIBUTE_REPARSE_POINT
    1024(0x400)

    具有关联重新解析点的文件或目录,或者是符号链接的文件。

    FILE_ATTRIBUTE_SPARSE_FILE
    512(0x200)

    一个稀疏文件的文件。

    FILE_ATTRIBUTE_SYSTEM
    4(0x4)

    操作系统使用部分或专门使用的文件或目录。

    FILE_ATTRIBUTE_TEMPORARY
    256(0x100)

    正在用于临时存储的文件。如果有足够的高速缓存可用,文件系统避免将数据写回大容量存储,因为通常,应用程序在关闭句柄后会删除临时文件。在这种情况下,系统可以完全避免写入数据。否则,手柄关闭后写入数据。

    FILE_ATTRIBUTE_VIRTUAL
    65536(0x10000)

    此值保留供系统使用。

      简单使用代码

     1 #include <stdio.h>
     2 #include <windows.h>
     3 #include <string>
     4 
     5 int main()
     6 {
     7     std::wstring wstrBeginDirName = L"C:\*.*";
     8     std::wstring wstrSearchName = L"ntdll";
     9 
    10     WIN32_FIND_DATAW findFile = { 0 };
    11 
    12     HANDLE hFileFind  = FindFirstFileW(wstrBeginDirName.c_str(), &findFile);
    13 
    14     do
    15     {
    16         printf("File name: %ls 
    ", findFile.cFileName);
    17     } while (FindNextFileW(hFileFind, &findFile));
    18 
    19     system("pause");
    20     return 0;
    21 }

    判断是否是文件夹

     1 #include <stdio.h>
     2 #include <windows.h>
     3 #include <string>
     4 
     5 int main()
     6 {
     7     system("color b");
     8     std::wstring wstrBeginDirName = L"C:\*.*";
     9     std::wstring wstrSearchName = L"ntdll";
    10 
    11     WIN32_FIND_DATAW findFile = { 0 };
    12 
    13     HANDLE hFileFind  = FindFirstFileW(wstrBeginDirName.c_str(), &findFile);
    14 
    15     do
    16     {
    17         if (findFile.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
    18             printf("Dir 			 %ls 
    ", findFile.cFileName);
    19         else
    20             printf("File 			 %ls 
    ", findFile.cFileName);
    21     } while (FindNextFileW(hFileFind, &findFile));
    22 
    23     system("pause");
    24     return 0;
    25 }

      重点:

        findFile.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY

          findFile.dwFileAttributes 一个多值的 不能使用 == 

          FILE_ATTRIBUTE_DIRECTORY  常量 16(0x10) 进行逻辑与运算

    递归搜索

     1 // Everything.cpp : 定义控制台应用程序的入口点。
     2 //
     3 
     4 #include "stdafx.h"
     5 #include <stdio.h>
     6 #include <windows.h>
     7 #include <string>
     8 
     9 //递归的方法继续搜索
    10 unsigned g_nFindedFileNum = 0;
    11 unsigned g_nSearchFileNum = 0;
    12 unsigned g_nSearchDirNum = 0;
    13 
    14 std::wstring MakeStandardDirName(const std::wstring &wstrDirname)
    15 {
    16     if (wstrDirname.back() != '\')
    17         return wstrDirname + L"\";
    18     return wstrDirname;
    19 }
    20 void MyFileFind(std::wstring &wstrBeginDirName, std::wstring &wstrSearch, std::wstring wstrFile = L"*.*")
    21 {
    22 
    23     WIN32_FIND_DATAW findFile = { 0 };
    24 
    25     HANDLE hFileFind = FindFirstFileW((MakeStandardDirName(wstrBeginDirName)+wstrFile).c_str(), &findFile);
    26 
    27     do
    28     {
    29         if (wcscmp(findFile.cFileName, L".") == 0)
    30             continue;
    31         if (wcscmp(findFile.cFileName, L"..") == 0)
    32             continue;
    33         if (findFile.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
    34             //printf("Dir 			 %ls 
    ", findFile.cFileName);
    35         {
    36             MyFileFind(MakeStandardDirName(wstrBeginDirName) + findFile.cFileName, wstrSearch);
    37             g_nSearchDirNum++;
    38         }
    39         else
    40             //printf("File 			 %ls 
    ", findFile.cFileName);
    41         {
    42             if (wcsstr(findFile.cFileName, wstrSearch.c_str()) != nullptr)
    43             {
    44                 printf("Searched File In:	 %ls 
    ",(MakeStandardDirName(wstrBeginDirName)+findFile.cFileName).c_str());
    45                 g_nFindedFileNum++;
    46             }
    47             g_nSearchFileNum++;
    48         }
    49     } while (FindNextFileW(hFileFind, &findFile));
    50 
    51 //    return g_nFindedFileNum;
    52 }
    53 
    54 int main()
    55 {
    56     system("color b");
    57     std::wstring wstrBeginDirName = L"C:\";
    58     std::wstring wstrSearchName = L"ntdll";
    59 
    60     DWORD dwBegin = GetTickCount();
    61     MyFileFind(wstrBeginDirName, wstrSearchName);
    62 
    63     DWORD dwTime = GetTickCount() - dwBegin;
    64     printf("耗费时间:%d(秒)
    合计找到:%d个文件
    共遍历过%d个文件夹和%d个文件!
    ",
    65         dwTime/1000, g_nFindedFileNum, g_nSearchDirNum, g_nSearchFileNum);
    66 
    67     system("pause");
    68     return 0;
    69 }

      重点:

        if (wcsstr(findFile.cFileName, wstrSearch.c_str()) != nullptr)

          比较字符串 是否存在,文件名称是否匹配

    递归的实现方法

     1 // Everything.cpp : 定义控制台应用程序的入口点。
     2 //
     3 
     4 #include "stdafx.h"
     5 #include <stdio.h>
     6 #include <windows.h>
     7 #include <string>
     8 #include <process.h>
     9 
    10 //递归的方法继续搜索
    11 unsigned g_nFindedFileNum = 0;
    12 unsigned g_nSearchFileNum = 0;
    13 unsigned g_nSearchDirNum = 0;
    14 
    15 std::wstring MakeStandardDirName(const std::wstring &wstrDirname)
    16 {
    17     if (wstrDirname.back() != '\')
    18         return wstrDirname + L"\";
    19     return wstrDirname;
    20 }
    21 void MyFileFind(std::wstring &wstrBeginDirName, std::wstring &wstrSearch, std::wstring wstrFile = L"*.*")
    22 {
    23 
    24     WIN32_FIND_DATAW findFile = { 0 };
    25 
    26     HANDLE hFileFind = FindFirstFileW((MakeStandardDirName(wstrBeginDirName)+wstrFile).c_str(), &findFile);
    27 
    28     do
    29     {
    30         if (wcscmp(findFile.cFileName, L".") == 0)
    31             continue;
    32         if (wcscmp(findFile.cFileName, L"..") == 0)
    33             continue;
    34         if (findFile.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
    35             //printf("Dir 			 %ls 
    ", findFile.cFileName);
    36         {
    37             MyFileFind(MakeStandardDirName(wstrBeginDirName) + findFile.cFileName, wstrSearch);
    38             g_nSearchDirNum++;
    39         }
    40         else
    41             //printf("File 			 %ls 
    ", findFile.cFileName);
    42         {
    43             if (wcsstr(findFile.cFileName, wstrSearch.c_str()) != nullptr)
    44             {
    45                 printf("Searched File In:	 %ls 
    ",(MakeStandardDirName(wstrBeginDirName)+findFile.cFileName).c_str());
    46                 g_nFindedFileNum++;
    47             }
    48             g_nSearchFileNum++;
    49         }
    50     } while (FindNextFileW(hFileFind, &findFile));
    51 
    52 //    return g_nFindedFileNum;
    53 }
    54 
    55 int main()
    56 {
    57     system("color b");
    58     std::wstring wstrBeginDirName = L"C:\";
    59     std::wstring wstrSearchName = L"ntdll";
    60 
    61     DWORD dwBegin = GetTickCount();
    62     MyFileFind(wstrBeginDirName, wstrSearchName);
    63 
    64     DWORD dwTime = GetTickCount() - dwBegin;
    65     printf("耗费时间:%d(秒)
    合计找到:%d个文件
    共遍历过%d个文件夹和%d个文件!
    ",
    66         dwTime/1000, g_nFindedFileNum, g_nSearchDirNum, g_nSearchFileNum);
    67 
    68     system("pause");
    69     return 0;
    70 }

    多线程实现发放

    // Everything.cpp : 定义控制台应用程序的入口点。
    //
    
    #include "stdafx.h"
    #include <stdio.h>
    #include <string>
    #include <process.h>
    #include <vector>
    #include <windows.h>
    
    //递归的方法继续搜索
    //unsigned g_nFindedFileNum = 0;
    //unsigned g_nSearchFileNum = 0;
    //unsigned g_nSearchDirNum = 0;
    
    std::wstring MakeStandardDirName(const std::wstring &wstrDirname)
    {
        if (wstrDirname.back() != '\')
            return wstrDirname + L"\";
        return wstrDirname;
    }
    //void MyFileFind(std::wstring &wstrBeginDirName, std::wstring &wstrSearch, std::wstring wstrFile = L"*.*")
    //{
    //
    //    WIN32_FIND_DATAW findFile = { 0 };
    //
    //    HANDLE hFileFind = FindFirstFileW((MakeStandardDirName(wstrBeginDirName) + wstrFile).c_str(), &findFile);
    //
    //    do
    //    {
    //        if (wcscmp(findFile.cFileName, L".") == 0)
    //            continue;
    //        if (wcscmp(findFile.cFileName, L"..") == 0)
    //            continue;
    //        if (findFile.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
    //            //printf("Dir 			 %ls 
    ", findFile.cFileName);
    //        {
    //            MyFileFind(MakeStandardDirName(wstrBeginDirName) + findFile.cFileName, wstrSearch);
    //            g_nSearchDirNum++;
    //        }
    //        else
    //            //printf("File 			 %ls 
    ", findFile.cFileName);
    //        {
    //            if (wcsstr(findFile.cFileName, wstrSearch.c_str()) != nullptr)
    //            {
    //                printf("Searched File In:	 %ls 
    ", (MakeStandardDirName(wstrBeginDirName) + findFile.cFileName).c_str());
    //                g_nFindedFileNum++;
    //            }
    //            g_nSearchFileNum++;
    //        }
    //    } while (FindNextFileW(hFileFind, &findFile));
    
        //    return g_nFindedFileNum;
    //}
    
    HANDLE g_hExitEvent;
    std::vector<HANDLE> g_hThreads;
    
    CRITICAL_SECTION g_cs;
    
    long g_lFindedFileNum = 0;
    long g_lSearchFileNum = 0;
    long g_lSearchDirNum = 0;
    long g_lWorkThreadNum = 0;
    
    struct ThreadData
    {
        std::wstring wstrDirName;
        std::wstring wstrSearch;
        std::wstring wstrFile; 
    };
    
    unsigned __stdcall ThreadFileFind(void *lParam)
    {
        InterlockedAdd(&g_lWorkThreadNum, 1);
    
        ThreadData *pData = (ThreadData*)lParam;
    
        WIN32_FIND_DATAW fileFind = { 0 };
        HANDLE hFileFind = FindFirstFileW(
            (MakeStandardDirName(pData->wstrDirName) + pData->wstrFile).c_str(), &fileFind);
        do
        {
            if (wcscmp(fileFind.cFileName, L".") == 0)
                continue;
            if (wcscmp(fileFind.cFileName, L"..") == 0)
                continue;
            if (fileFind.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
            {
                ThreadData *pTempData = new ThreadData;
                pTempData->wstrDirName = MakeStandardDirName(pData->wstrDirName) + fileFind.cFileName;
                pTempData->wstrFile = pData->wstrFile;
                pTempData->wstrSearch = pData->wstrSearch;
    
                //上锁
                EnterCriticalSection(&g_cs);
    
                CloseHandle((HANDLE)_beginthreadex(nullptr, 0, ThreadFileFind, pTempData, 0, nullptr));
                //g_hThreads.push_back((HANDLE)_beginthreadex(nullptr, 0, ThreadFileFind, pTempData, 0, nullptr));
    
                LeaveCriticalSection(&g_cs);
    
                //原子操作
                InterlockedAdd(&g_lSearchDirNum, 1);
            }
            else
            {
                if(wcsstr(fileFind.cFileName,pData->wstrSearch.c_str()) != nullptr)
                {
                    printf("Searched File In:	 %ls 
    ", (MakeStandardDirName(pData->wstrDirName) + fileFind.cFileName).c_str());
                    InterlockedAdd(&g_lFindedFileNum, 1);
                }
                InterlockedAdd(&g_lSearchFileNum, 1);
            }
    
        } while (FindNextFileW(hFileFind,&fileFind));
        delete pData;
    
        InterlockedAdd(&g_lWorkThreadNum, -1);
        if (g_lWorkThreadNum == 0)
            SetEvent(g_hExitEvent);
        return 0;
    }
    
    int main()
    {
        //初始化锁
        InitializeCriticalSection(&g_cs);
    
        g_hExitEvent =  CreateEvent(nullptr, FALSE, FALSE, nullptr);
    
        ThreadData *pTempData = new ThreadData;
        pTempData->wstrDirName = L"C:";
        pTempData->wstrFile = L"*.*";
        pTempData->wstrSearch = L"ntdll";
    
        DWORD dwBegin = GetTickCount();
        CloseHandle((HANDLE)_beginthreadex(nullptr, 0, ThreadFileFind, pTempData, 0, nullptr));
        //g_hThreads.push_back((HANDLE)_beginthreadex(nullptr, 0, ThreadFileFind, pTempData, 0, nullptr));
    
        //WaitForMultipleObjects(g_hThreads.size(), g_hThreads.data(), TRUE, INFINITE);
    
        WaitForSingleObject(g_hExitEvent, INFINITE);
    
        DWORD dwTime = GetTickCount() - dwBegin;
    
        //关闭句柄
        for (auto g_h_thread : g_hThreads)
        {
            CloseHandle(g_h_thread);
        }
    
        DeleteCriticalSection(&g_cs);
    
    
        printf("耗费时间:%d(秒)
    合计找到:%d个文件
    共遍历过%d个文件夹和%d个文件!
    ",
            dwTime / 1000, g_lFindedFileNum, g_lSearchDirNum, g_lSearchFileNum);
    
        //什么时候搜索完成
    
        //system("color b");
        //std::wstring wstrBeginDirName = L"C:\";
        //std::wstring wstrSearchName = L"ntdll";
    
        //DWORD dwBegin = GetTickCount();
        //MyFileFind(wstrBeginDirName, wstrSearchName);
    
        //DWORD dwTime = GetTickCount() - dwBegin;
        //printf("耗费时间:%d(秒)
    合计找到:%d个文件
    共遍历过%d个文件夹和%d个文件!
    ",
        //    dwTime / 1000, g_nFindedFileNum, g_nSearchDirNum, g_nSearchFileNum);
    
        system("pause");
        return 0;
    }

  • 相关阅读:
    [学习日记]进程、线程和模块
    [学习日记]对SOAP头内添加信息的验证,可实现对请求WEB服务进行身份验证。
    [梦里原创]关于猫和老鼠的问题(程序算法)
    [学习日记]对控件的继承和重载
    [学习日记]VB图像处理之像素的获取和输出
    猫和老鼠问题的讨论
    [音乐欣赏]丁香花
    推荐一个WINDOWS系统文件介绍的网站
    [转]查查在中国有多少人的名字和你一样!
    计算机语言发展图解
  • 原文地址:https://www.cnblogs.com/sdk123/p/7372816.html
Copyright © 2011-2022 走看看