我正在开发一个必须在Windows操作系统上管理文件的C ++控制台应用程序。我需要获取具有特定扩展名的文件名“列表”。我找到了很多解决方案,建议最多的是以下一个:
HANDLE hFind;
WIN32_FIND_DATA data;
hFind = FindFirstFile("C:\\PWS\\*.sda", &data);
if (hFind != INVALID_HANDLE_VALUE) {
do {
cout << data.cFileName << endl;
} while (FindNextFile(hFind, &data));
FindClose(hFind);
}
假设我在C:\\PWS
文件夹中有这些文件:
上面的代码打印了所有代码,而我只需要f002.sda
和f004.sda
。
任何提示?
NB
:我不想使用boost库。
答案 0 :(得分:2)
代码还会找到"f001.sdac"
和"f003.sdab"
,因为FindFirstFile()
和FindFirstFileEx()
都匹配短文件名(8.3)和长文件名。例如,"f001.sdac"
的短文件名可能类似于"f~1.sda"
。
原因是backwards compatibility with 16-bit (sigh!) programs。
要解决此问题,请使用FindFirstFile()
通配符调用*
以匹配所有文件,然后执行自己的过滤,例如调用PathMatchSpec()
函数。 PathMatchSpec()
仅进行字符串匹配,因此它不具有FindFirstFile()
的奇怪行为。
WIN32_FIND_DATAW data;
HANDLE hFind = FindFirstFileW( L"C:\\PWS\\*", &data );
if( hFind != INVALID_HANDLE_VALUE )
{
do
{
if( ( data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) == 0 &&
PathMatchSpecW( data.cFileName, L"*.sda" ) )
{
std::wcout << data.cFileName << std::endl;
}
}
while( FindNextFileW( hFind, &data ) );
FindClose( hFind );
}
旁注:为FindFirstFileEx()
参数调用值为FindExInfoBasic
的{{1}},据说&#34; 不查询短文件名&#34;,不是此问题的有效解决方案,因为它仍将匹配短(8.3)文件名。
答案 1 :(得分:0)
这样的事情应该为你过滤结果:
bool hasFileExtension(TCHAR cFileName[], TCHAR* ptcExtension)
{
bool result = true;
int iFileNameLength = _tcslen(cFileName);
int iExtensionLength = _tcslen(ptcExtension);
if (iFileNameLength >= iExtensionLength)
{
for (int i = 1; i < iExtensionLength + 1 && result; i++)
{
if (cFileName[iFileNameLength - i] != ptcExtension[iExtensionLength - i])
{
result = false;
}
}
}
else
{
result = false;
}
return result;
}
void listFilesWithExtension(LPCTSTR lpFileName, TCHAR* ptcExtension)
{
HANDLE hFind;
WIN32_FIND_DATA data;
hFind = FindFirstFile(lpFileName, &data);
if (hFind != INVALID_HANDLE_VALUE) {
do {
if (hasFileExtension(data.cFileName, ptcExtension))
{
wcout << data.cFileName << endl;
}
} while (FindNextFile(hFind, &data));
FindClose(hFind);
}
}
int main()
{
LPCTSTR lpFileName = L"C:\\PWS\\*.sda";
TCHAR* ptcExtension = _T(".sda");
listFilesWithExtension(lpFileName, ptcExtension);
Sleep(5000);
return 0;
}
答案 2 :(得分:0)
我采用的解决方案如下:
void GetFilesByNameRootAndExtension(const string& dirPath, const string& nameRoot, string& ext, vector<string>& files)
{
files.clear();
stringstream ss;
ss << dirPath << "\\" << nameRoot << "*" << ext;
string searchKeyS = ss.str();
const char* searchKey = searchKeyS.c_str();
WIN32_FIND_DATA data;
HANDLE hFind = FindFirstFile(searchKey, &data);
ext = ext.erase(0, 1);
if (hFind != INVALID_HANDLE_VALUE) {
do {
string fN = data.cFileName;
if (fN.substr(fN.find_last_of(".") + 1) == ext) // filtering by extension
files.push_back(fN);
} while (FindNextFile(hFind, &data));
FindClose(hFind);
}
}
谢谢大家的提示!