2014-06-12 2 views
1

Windows 파일 시스템은 대소 문자를 구분하지 않습니다. 파일 경로가있을 때 파일 시스템에있는 것과 정확하게 일치하는 사례를 원합니다. 지금 당장이 코드를 사용하여 다음 코드를 사용하고 있습니다.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

는 Windows 원래 사건에 대해 상관하지 않는다 알고 있다면 왜 당신이 필요합니까? –

+0

왜냐하면 문자열의 텍스트 표현이 필요하고 다른 대소 문자를 구분하는 시스템에서 파일을 식별하기 위해 고소했기 때문입니다. – gsf

+0

'FindFirstFile()'의 속도를 높일 수는 없지만 코드의 나머지 부분은 빠르게 할 수 있습니다 'split()'을 사용하거나 새로운'path'를 동적으로 빌드하십시오. 직접 원래의'api' 경로를 반복하십시오. 구분 기호가 발생할 때마다 일시적으로 '\ 0'으로 바꾸고 원래의 'api'문자열을 사용하여'FindFirstFile()'을 호출 한 다음 구분 기호를 복원하고 그 구분 기호와 마지막 구분 기호 사이의 모든 것을 찾은 결과로 대체하십시오 . 대소 문자를 변경해도 크기가 다른 하위 문자열이 생성되지 않는 한 모든 메모리 할당을 수행 할 필요가 없습니다. –

답변

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; 
} 
관련 문제