2011-12-14 3 views
4

2 개의 문자열이 파일 시스템 경로 (디렉토리)에서 동일한 지 확인하는 방법을 찾고 있습니다. /y/x에 대한 기호 링크가있는 경우에도, /x/y 없습니다 - {/x, \x, //x, /x/}하지만,이 두 사람은 예를 들어이 세트의 모든 문자열은 파일 시스템 경로의 측면에서 동일합니다. 필자가 작성하려고하는 프로그램은 Windows와 마찬가지로 Linux에서도 작동해야하므로 휴대용 솔루션을 찾고 있습니다.C++에서 (경로) 경로를 비교하는 방법은 무엇입니까?

편집 :

난 단지 부스트의 헤더 - 라이브러리 만 사용하고, 그래서 boost::filesystem와 솔루션은 나를 위해 확인되지 않습니다. Windows API에 UrlCompare이 있다는 것을 알고 있습니다. Linux에 뭔가 있습니까?

+2

+1 좋은 질문입니다. 부스트 할 수있는 대안이 있습니까? – Walter

+0

지금 헤더 전용 부스트를 사용하고 있는데, 왜 lib 의존성을 추가하지 않는 이유가 무엇입니까? –

+0

@Tomalak Garet'kal : Sun Studio 5.7에서 컴파일 컴파일에 몇 가지 문제가 있기 때문에 –

답변

2

boost::filesystem 라이브러리를 사용하십시오. 경로 비교 기능이 있습니다.

편집 : apr을 시도 할 수 있습니다. 예, C++이 아니지만 이식 가능합니다.

1

이식성 측면에서 Boost 파일 시스템 라이브러리가 유용 할 수 있습니다 (documentation link). 더 구체적으로 말하자면 : path.hpp은 경로 비교를 사용할 수있는 곳에서 가장 유용합니다. gmane.org에

편집

This 논의는 boost::filesystem 최소한의 헤더 전용 버전을 간주한다. 요약하면 : 이것은 존재하지 않습니다. 따라서 자신 만의 추상화 라이브러리를 구축하고 크로스 플랫폼 기능을 제공하게 될 것입니다.

Linux에서는 dirent.h이 POSIX C 라이브러리입니다. Windows의 경우 Win32 API를 사용해야합니다. 그러나 교차 플랫폼으로 보이는 이른바 "디렉토리 - 스트림 라이브러리"도 있습니다. here (웹 사이트는 독일어로되어 있습니다).

3

부스트가 아닌 솔루션에는 시스템 종속 코드 (부스트를 사용하는 경우 부스트에 숨겨진 )가 포함됩니다. 정확히 을 "일치"로 정의해야합니다 : "./MyFile.xxx""MyFile.xxx" 은 같아야합니까? "aaa/.../MyFile.xxx""MyFile.xxx"은 어떨까요? 나는이 문제를 해결할 것

하는 방법은 두 가지 데이터 멤버, (항상 유닉스 빈 일 것)을 “ 접두사 ”과 std::string 및 경로 모든 요소를 ​​가진 std::vector<std::string>로 클래스를 정의하는 것입니다. 이 클래스는 필요한 비교 함수가 점으로 찍혀 있고 생성자를 구현하기 위해 시스템 종속 코드를 사용합니다. 생성자 자체는 소스 파일에 있고 소스 파일에는 컴퓨터 종속 헤더가 포함됩니다 (일반적으로 각 변형에 대해 별도의 디렉토리를 사용하고 은 -I 또는 /I으로 헤더를 선택하여 사용할 디렉토리를 지정합니다).).헤더에 들어갈 수있는 것 의 종류 : 유닉스에 대한

inline bool 
isPathSeparator(char ch) 
{ 
    return ch == '/'; 
} 

std::string 
getHeader(std::string const& fullPathName) 
{ 
    return ""; 
} 

bool 
charCompare(char lhs, char rhs) 
{ 
    return lhs < rhs; 
} 

bool 
charMatch(char lhs, char rhs) 
{ 
    return lhs == rhs; 
} 

와 Windows 용

inline bool 
isPathSeparator(char ch) 
{ 
    return ch == '/' || ch == '\\'; 
} 

std::string 
getHeader(std::string const& fullPathName) 
{ 
    return fullPathName.size() > 2 && fullPathName[1] == ':' 
     ? fullPathName.substr(0, 2) 
     : std::string(); 
} 

bool 
charCompare(char lhs, char rhs) 
{ 
    return tolower((unsigned char)lhs) < tolower((unsigned char)rhs); 
} 

bool 
charMatch(char lhs, char rhs) 
{ 
    return tolower((unsigned char)lhs) == tolower((unsigned char)rhs); 
} 

.

생성자는 다음 헤더를 초기화 getHeader을 사용

및 요소들로 문자열을 깨는 input.begin() + header.size()input.end() 이상 반복 할. "." 요소가있는 경우 을 무시하고 ".." 중 하나 인 경우 을 사용하여 경로가 비어 있지 않으면 경로의 상위 요소 인 을 제거하십시오. 그 후,이 charComparechar에 대한 charMatchstd::lexicographical_compare 또는 std::equal를 사용하는 비교기를 정의 단지 질문입니다 (새 클래스 아마 또한 등) std::string의 비교기와 (크기가 동일한 것을 확인 후) . 다음과 같이 입력하십시오 :

struct FileNameCompare 
{ 
    bool operator()(char lhs, char rhs) const 
    { 
     return charCompare(lhs, rhs); 
    } 
    bool operator()(std::string const& lhs, std::string const& rhs) const 
    { 
     return std::lexicographical_compare(
      lhs.begin(), lhs.end(), 
      rhs.begin(), rhs.end(), 
      *this); 
    } 
    bool operator()(FileName const& lhs, FileName const& rhs) const 
    { 
     return (*this)(lhs.prefix, rhs.prefix) 
      || (!(*this)(rhs.prefix, lhs.prefix) 
       && std::lexicographical_compare(
        lhs.elements.begin(), lhs.elements.end(), 
        rhs.elements.begin(), rhs.elements.end(), 
        *this)); 
    } 
}; 

struct FileNameMatch 
{ 
    bool operator()(char lhs, char rhs) const 
    { 
     return charMatch(lhs, rhs); 
    } 
    bool operator()(std::string const& lhs, std::string const& rhs) const 
    { 
     return lhs.size() == rhs.size() 
      && std::equal(lhs.begin(), lhs.end(), rhs.begin(), *this); 
    } 
    bool operator()(FileName const& lhs, FileName const& rhs) const 
    { 
     return (*this)(lhs.prefix, rhs.prefix) 
      && lhs.elements.size() == rhs.elements.size() 
      && std::equal(lhs.elements.begin(), lhs.elements.end(), 
          rhs.elements.begin(), 
          *this); 
    } 
}; 

트릭을해야합니다. (그냥 operator()(char, char) const 소스 파일에 있어야 기억, 당신은 charComparecharMatch를 정의하는 시스템에 의존 헤더를 포함하지 않습니다 헤더, 에서 그들을 인라인 수 없습니다.)

0
std::string path1 = "c:\\folder\\"; 
std::string path2 = "c:\\folder\\folder\\..\\"; 

boost::filesystem::equivalent(boost::filesystem::path(path1), boost::filesystem::path(path2) 

코드를 폴더가 실제로 동일하기 때문에 true을 반환합니다.

+0

OP는 "boost :: filesystem의 솔루션이 문제가 아닙니다."라고 대답했습니다. 대안을 찾고 있습니다. –

관련 문제