Windows文件系统不区分大小写。当我有一个文件路径时,我希望这些案例与文件系统中的情况完全一样。现在我使用以下代码来确保这一点:
std::vector<std::wstring> directories;
boost::split(directories, api, is_any_delimiter);
size_t i = 0;
std::wstring path;
if (hasWindowsDriverLetter())
{
path += directories[i++];
}
std::wstring delimiter(L"\\");
for (;i < directories.size(); ++i)
{
std::wstring search = path + delimiter + directories[i];
WIN32_FIND_DATAW FindFileData;
HANDLE hFind = FindFirstFileW(search.c_str(), &FindFileData);
if (hFind == INVALID_HANDLE_VALUE)
{
path = search;
continue;
}
path += delimiter + FindFileData.cFileName;
::FindClose(hFind);
}
我的功能在性能敏感的地方 - 有更有效的方法吗?
注意:GetLongPathNameW
不起作用。
答案 0 :(得分:0)
尝试这样的事情:
std::wstring::iterator GetIteratorAfterRoot(std::wstring &str)
{
std::wstring::iterator iter = str.begin();
wchar_t *tmp = str.c_str();
wchar_t *tmp2;
if (PathCchSkipRoot(tmp, &tmp2) == S_OK)
iter += std::distance(tmp, tmp2);
return iter;
}
std::wstring api = ...;
std::wstring start = GetIteratorAfterRoot(api);
std::wstring end = api.end();
WIN32_FIND_DATAW FindFileData;
HANDLE hFind;
bool finished = false;
while (start != end)
{
std::wstring::iterator found = std::find_if(start, end, is_any_delimiter);
if (found != end)
{
wchar_t delim = *found;
*found = L'\0';
hFind = FindFirstFileW(api.c_str(), &FindFileData);
*found = delim;
}
else
{
finished = true;
hFind = FindFirstFileW(api.c_str(), &FindFileData);
}
if (hFind != INVALID_HANDLE_VALUE)
{
::FindClose(hFind);
std::wstring::difference_type SearchLength = std::distance(start, found);
int FileNameLength = lstrlenW(FindFileData.cFileName);
if (SearchLength != FileNameLength)
{
// string length is changing...
if (finished)
{
api.replace(start, found, FindFileData.cFileName);
break;
}
std::wstring::difference_type SearchOffset = std::distance(api.begin(), start);
api.replace(start, found, FindFileData.cFileName);
start = api.begin() + (SearchOffset + FileNameLength + 1);
end = api.end();
continue;
}
// string length not changing, copy new name inlined...
// not sure if std::wstring::replace() is smart enough to do an
// inline copy if the two lengths match, so using std::copy instead...
//api.replace(start, found, FindFileData.cFileName);
std::copy(FindFileData.cFileName, &FindFileData.cFileName[FileNameLength], start);
}
if (finished)
break;
start = found + 1;
}