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:\Windows\System32\*.dll //在c:\Windows\System32目錄中查找所有dll文件 c:\Windows\System.ini; //在c:\Windows目錄中查找System.ini文件 c:\Windows\a???.* //在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和主題的列表,請參閱另請參閱部分。
恒/值 | 描述 |
---|---|
|
作為歸檔文件或目錄的文件或目錄。應用程序通常使用此屬性來標記文件進行備份或刪除。 |
|
被壓縮的文件或目錄。對於一個文件,文件中的所有數據都被壓縮。對於目錄,壓縮是新創建的文件和子目錄的默認值。 |
|
此值保留供系統使用。 |
|
標識目錄的句柄。 |
|
加密的文件或目錄。對於一個文件,文件中的所有數據流都被加密。對於目錄,加密是新創建的文件和子目錄的默認值。 |
|
該文件或目錄被隱藏。它不包括在普通目錄列表中。 |
|
目錄或用戶數據流配置完整性(僅在ReFS卷上支持)。它不包括在普通目錄列表中。如果文件被重命名,則完整性設置將與文件保持一致。如果文件被復制,則如果源文件或目標目錄具有完整性集,則目標文件將具有完整性集。 Windows Server 2008 R2,Windows 7,Windows Server 2008,Windows Vista,Windows Server 2003和Windows XP: Windows Server 2012之前不支持此標誌。 |
|
沒有設置其他屬性的文件。此屬性僅在單獨使用時有效。 |
|
文件或目錄不被內容索引服務編入索引。 |
|
用戶數據流不被背景數據完整性掃描器(AKA scrubber)讀取。當設置在目錄上時,它只提供繼承。此標誌僅在存儲空間和ReFS卷上受支持。它不包括在普通目錄列表中。 Windows Server 2008 R2,Windows 7,Windows Server 2008,Windows Vista,Windows Server 2003和Windows XP: Windows 8和Windows Server 2012之前不支持此標誌。 |
|
文件的數據不可用。該屬性表示文件數據被物理移動到離線存儲。該屬性由分層存儲管理軟件Remote Storage使用。應用程序不應該隨意更改此屬性。 |
|
只讀的文件。應用程序可以讀取文件,但不能寫入或刪除它。該屬性不符合目錄。有關詳細信息, |
|
設置此屬性時,表示文件或目錄在本地不完全存在。對於一個文件,意味著並不是所有的數據都在本地存儲上(例如,它可能是稀疏的,還有一些數據仍在遠程存儲中)。對於目錄,這意味著某些目錄內容正在從另一個位置進行虛擬化。讀取文件/枚舉目錄將比正常情況更昂貴,例如,將導致至少一些文件/目錄內容從遠程存儲提取。只有內核模式的呼叫者可以設置這個位。 |
|
此屬性僅顯示在目錄枚舉類(FILE_DIRECTORY_INFORMATION,FILE_BOTH_DIR_INFORMATION等)中。當設置此屬性時,表示文件或目錄在本地系統上沒有物理表示; 該項目是虛擬的。打開該項目將比正常更昂貴,例如,它會導致至少一些從遠程商店獲取。 |
|
具有關聯重新解析點的文件或目錄,或者是符號鏈接的文件。 |
|
一個稀疏文件的文件。 |
|
操作系統使用部分或專門使用的文件或目錄。 |
|
正在用於臨時存儲的文件。如果有足夠的高速緩存可用,文件系統避免將數據寫回大容量存儲,因為通常,應用程序在關閉句柄後會刪除臨時文件。在這種情況下,系統可以完全避免寫入數據。否則,手柄關閉後寫入數據。 |
|
此值保留供系統使用。 |
簡單使用代碼
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 \r\n", 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 \t\t\t %ls \r\n", findFile.cFileName); 19 else 20 printf("File \t\t\t %ls \r\n", 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 \t\t\t %ls \r\n", findFile.cFileName); 35 { 36 MyFileFind(MakeStandardDirName(wstrBeginDirName) + findFile.cFileName, wstrSearch); 37 g_nSearchDirNum++; 38 } 39 else 40 //printf("File \t\t\t %ls \r\n", findFile.cFileName); 41 { 42 if (wcsstr(findFile.cFileName, wstrSearch.c_str()) != nullptr) 43 { 44 printf("Searched File In:\t %ls \r\n",(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(秒)\r\n合計找到:%d個文件\r\n共遍歷過%d個文件夾和%d個文件!\r\n", 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 \t\t\t %ls \r\n", findFile.cFileName); 36 { 37 MyFileFind(MakeStandardDirName(wstrBeginDirName) + findFile.cFileName, wstrSearch); 38 g_nSearchDirNum++; 39 } 40 else 41 //printf("File \t\t\t %ls \r\n", findFile.cFileName); 42 { 43 if (wcsstr(findFile.cFileName, wstrSearch.c_str()) != nullptr) 44 { 45 printf("Searched File In:\t %ls \r\n",(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(秒)\r\n合計找到:%d個文件\r\n共遍歷過%d個文件夾和%d個文件!\r\n", 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 \t\t\t %ls \r\n", findFile.cFileName); // { // MyFileFind(MakeStandardDirName(wstrBeginDirName) + findFile.cFileName, wstrSearch); // g_nSearchDirNum++; // } // else // //printf("File \t\t\t %ls \r\n", findFile.cFileName); // { // if (wcsstr(findFile.cFileName, wstrSearch.c_str()) != nullptr) // { // printf("Searched File In:\t %ls \r\n", (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:\t %ls \r\n", (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(秒)\r\n合計找到:%d個文件\r\n共遍歷過%d個文件夾和%d個文件!\r\n", 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(秒)\r\n合計找到:%d個文件\r\n共遍歷過%d個文件夾和%d個文件!\r\n", // dwTime / 1000, g_nFindedFileNum, g_nSearchDirNum, g_nSearchFileNum); system("pause"); return 0; }
Windows 實戰項目 001 文件掃描器 (01)