我是C++的新手,我需要在驱动器中搜索一个特定的文件并显示它们,或者将它们列在一个列表框中。
到目前为止我的情况是这样的。我在论坛上找到了一些零碎的东西,我还添加了一些东西。
我的问题是如何把它们组合在一起。假设我在搜索一个名为"test.txt“的文件
谢谢!
// search for drives
char* szSingleDrive;
DWORD dwSize = MAX_PATH;
char szLogicalDrives[MAX_PATH] = { 0 };
DWORD dwResult = GetLogicalDriveStrings(dwSize, szLogicalDrives);
UINT logicalDrive = GetDriveType(szLogicalDrives);
bool IsPhysicalDrive(string drives)
{
if (logicalDrive == 3)
{
return logicalDrive;
}
}
// function to look thru directories.
void FindFile(std::string directory)
{
std::string tmp = directory + "\\*";
WIN32_FIND_DATA file;
HANDLE search_handle = FindFirstFile(tmp.c_str(), &file);
if (search_handle != INVALID_HANDLE_VALUE)
{
std::vector<std::wstring> directories;
do
{
//std::wcout << file.cFileName << std::endl;
//::MessageBox(NULL, file.cFileName, "", MB_OK); // message box to verify that it's working
if (file.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
{
if ((!lstrcmp(file.cFileName, ".")) || (!lstrcmp(file.cFileName, "..")))
continue;
}
//std::wcout << file.cFileName << std::endl;
::MessageBox(NULL, file.cFileName, "", MB_OK);
directory += "\\" + std::string(file.cFileName);
FindFile(directory);
}
while (FindNextFile(search_handle, &file));
if (GetLastError() != 18) // Error code 18: No more files left
FindClose(search_handle);
//CloseHandle(search_handle);
}
}
FindFile("C:\\"); // <-- this should spin thru different drives (physical drives from the function)
发布于 2020-04-23 00:04:28
尝试更像这样的东西:
void FindFile(const std::string &directory)
{
std::string dir = directory;
if ((!dir.empty()) && (dir.back() != '\\') && (dir.back() != '/'))
dir += '\\';
WIN32_FIND_DATAA file;
HANDLE search_handle = FindFirstFileA((dir + "*").c_str(), &file);
if (search_handle == INVALID_HANDLE_VALUE)
{
if (GetLastError() != ERROR_FILE_NOT_FOUND)
{
// error handling...
}
}
else
{
//std::vector<std::string> subdirs;
do
{
if (file.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
{
if ((lstrcmpA(file.cFileName, ".") != 0) && (lstrcmpA(file.cFileName, "..") != 0))
{
//std::cout << file.cFileName << std::endl;
::MessageBox(NULL, file.cFileName, "", MB_OK);
//subdirs.push_back(file.cFileName);
FindFile(dir + file.cFileName);
}
}
else
{
if (lstrcmpA(file.cFileName, "test.txt") == 0)
{
::MessageBox(NULL, dir.c_str(), "FOUND IN DIR", MB_OK);
}
}
}
while (FindNextFileA(search_handle, &file));
if (GetLastError() != ERROR_NO_MORE_FILES)
{
// error handling...
}
FindClose(search_handle);
/*
for(size_t i = 0; i < subdirs.size(); ++i)
FindFile(dir + subdirs[i]);
*/
}
}
然后你可以这样做:
DWORD dwSize = MAX_PATH;
char szLogicalDrives[MAX_PATH];
DWORD dwResult = GetLogicalDriveStrings(dwSize, szLogicalDrives);
if (dwResult == 0)
{
// error handling...
}
else if (dwResult > MAX_PATH)
{
// not enough buffer space...
}
else
{
for(char* szSingleDrive = szLogicalDrives; *szSingleDrive != 0; szSingleDrive += (lstrlenA(szSingleDrive)+1))
{
if (GetDriveTypeA(szSingleDrive) == DRIVE_FIXED)
FindFile(szSingleDrive);
}
}
或者这个:
DWORD dwLogicalDrives = GetLogicalDrives();
if (dwLogicalDrives == 0)
{
// error handling...
}
else
{
char szSingleDrive[] = "_:\\";
for (DWORD i = 0; i < 26; ++i)
{
if (dwLogicalDrives & (1 << i))
{
szSingleDrive[0] = 'A' + i;
if (GetDriveTypeA(szSingleDrive) == DRIVE_FIXED)
FindFile(szSingleDrive);
}
}
}
发布于 2020-04-23 06:49:58
您还可以使用窗口搜索服务而不是递归函数。这将大大提高搜索速度。
首先,您需要确保索引驱动器:控制面板>索引选项>修改,检查文件。
然后可以使用Windows Search作为示例:
#include <windows.h>
#include <searchapi.h>
#include <iostream>
#include <atldbcli.h>
using namespace std;
class CMyAccessor
{
public:
WCHAR _szItemUrl[2048];
__int64 _size;
BEGIN_COLUMN_MAP(CMyAccessor)
COLUMN_ENTRY(1, _szItemUrl)
COLUMN_ENTRY(2, _size)
END_COLUMN_MAP()
};
HRESULT GetSQLStringFromParams(LCID lcidContentLocaleParam,
PCWSTR pszContentPropertiesParam,
LCID lcidKeywordLocaleParam,
LONG nMaxResultsParam,
PCWSTR pszSelectColumnsParam,
PCWSTR pszSortingParam,
SEARCH_QUERY_SYNTAX sqsSyntaxParam,
SEARCH_TERM_EXPANSION steTermExpansionParam,
PCWSTR pszWhereRestrictionsParam,
PCWSTR pszExprParam,
PWSTR* ppszSQL)
{
ISearchQueryHelper* pQueryHelper;
// Create an instance of the search manager
ISearchManager* pSearchManager;
HRESULT hr = CoCreateInstance(__uuidof(CSearchManager), NULL, CLSCTX_LOCAL_SERVER, IID_PPV_ARGS(&pSearchManager));
if (SUCCEEDED(hr))
{
// Get the catalog manager from the search manager
ISearchCatalogManager* pSearchCatalogManager;
hr = pSearchManager->GetCatalog(L"SystemIndex", &pSearchCatalogManager);
if (SUCCEEDED(hr))
{
// Get the query helper from the catalog manager
hr = pSearchCatalogManager->GetQueryHelper(&pQueryHelper);
if (SUCCEEDED(hr))
{
hr = pQueryHelper->put_QueryContentLocale(lcidContentLocaleParam);
if (SUCCEEDED(hr))
{
hr = pQueryHelper->put_QueryContentProperties(pszContentPropertiesParam);
}
if (SUCCEEDED(hr))
{
hr = pQueryHelper->put_QueryKeywordLocale(lcidKeywordLocaleParam);
}
if (SUCCEEDED(hr))
{
hr = pQueryHelper->put_QueryMaxResults(nMaxResultsParam);
}
if (SUCCEEDED(hr))
{
hr = pQueryHelper->put_QuerySelectColumns(pszSelectColumnsParam);
}
if (SUCCEEDED(hr))
{
hr = pQueryHelper->put_QuerySorting(pszSortingParam);
}
if (SUCCEEDED(hr))
{
hr = pQueryHelper->put_QuerySyntax(sqsSyntaxParam);
}
if (SUCCEEDED(hr))
{
hr = pQueryHelper->put_QueryTermExpansion(steTermExpansionParam);
}
if (SUCCEEDED(hr))
{
hr = pQueryHelper->put_QueryWhereRestrictions(pszWhereRestrictionsParam);
}
if (SUCCEEDED(hr))
{
hr = pQueryHelper->GenerateSQLFromUserQuery(pszExprParam, ppszSQL);
}
pQueryHelper->Release();
}
pSearchCatalogManager->Release();
}
pSearchManager->Release();
}
return hr;
}
void WindowsSearch(PCWSTR indexed_drive)
{
PWSTR pszSQL;
wstring script = L"AND SCOPE ='file:///";
script += indexed_drive;
script += L"'";
HRESULT hr = GetSQLStringFromParams(1033, L"", 1033, -1, L"System.ItemPathDisplay, System.Size",
L"", SEARCH_ADVANCED_QUERY_SYNTAX, SEARCH_TERM_NO_EXPANSION, script.c_str(),
L"FileName:test.txt", &pszSQL);
if (SUCCEEDED(hr))
{
wcout << L"Generated query: " << pszSQL << endl;
CDataSource cDataSource;
hr = cDataSource.OpenFromInitializationString(L"provider=Search.CollatorDSO.1;EXTENDED PROPERTIES='Application=Windows'");
if (SUCCEEDED(hr))
{
CSession cSession;
hr = cSession.Open(cDataSource);
if (SUCCEEDED(hr))
{
// cCommand is derived from CMyAccessor which has binding information in column map
// This allows ATL to put data directly into apropriate class members.
CCommand<CAccessor<CMyAccessor>, CRowset> cCommand;
hr = cCommand.Open(cSession, pszSQL);
if (SUCCEEDED(hr))
{
__int64 maxValue = 0;
__int64 minValue = ULONG_MAX;
for (hr = cCommand.MoveFirst(); S_OK == hr; hr = cCommand.MoveNext())
{
wcout << cCommand._szItemUrl << L": " << cCommand._size << L" bytes" << endl;
maxValue = max(maxValue, cCommand._size);
minValue = min(minValue, cCommand._size);
}
wcout << L"Max:" << maxValue << L"Min:" << minValue << endl;
cCommand.Close();
}
cCommand.ReleaseCommand();
}
}
CoTaskMemFree(pszSQL);
}
}
int main()
{
DWORD dwLogicalDrives = GetLogicalDrives();
HRESULT hr = CoInitializeEx(NULL, COINIT_MULTITHREADED | COINIT_DISABLE_OLE1DDE);
if (SUCCEEDED(hr) && dwLogicalDrives != 0)
{
WCHAR szSingleDrive[] = L"_:\\";
for (DWORD i = 0; i < 26; ++i)
{
if (dwLogicalDrives & (1 << i))
{
szSingleDrive[0] = 'A' + i;
if (GetDriveTypeW(szSingleDrive) == DRIVE_FIXED)
WindowsSearch(szSingleDrive);
}
}
CoUninitialize();
}
}
发布于 2020-04-23 09:33:42
您可以将std::filesystem
与C++17结合使用,请注意,由于它是一个可选的规范,许多编译器都可以使用它。您还可以使用boost::filesystem
作为替代项,或基于C++17 filesystem
规范的这标头专用库。
要用std::filesystem
递归地查找单个文件,您可以执行如下操作:
std::filesystem::path top_level_dir("/");
for (const auto& file_iter : std::filesystem::recursive_directory_iterator(top_level_dir) {
if (!std::filesystem::is_directory(file_iter.path()) {
if (file_iter.path() == search_filename) {
// Here we have found the file
}
}
}
(search_filename
是要搜索的文件的文件名)
这比使用windows要简洁得多,而且更易于移植(请注意我是如何在用于top_level_dir
的路径中使用正斜杠的)。
https://stackoverflow.com/questions/61375911
复制相似问题