2011-12-14 18 views
4

ファイルシステムのパス(ディレクトリ)に関して2つの文字列が同じかどうかを調べる方法を探しています。 {/x\x//x/x/}が、この二 - /x/y/y/xへのシンボリックリンクであっても、されないが、例えば、このセットからすべての文字列はファイルシステムのパスの点で同じです。私が書くつもりのプログラムは、Windowsと同様にLinuxでも動作するはずなので、私はポータブルなソリューションを探しています。C++の(ディレクトリ)パスを比較するには?

EDIT:

私はブーストのヘッダーのみのみのLIBSを使用していますので、boost::filesystemとソリューションは、私にとってはOKではありません。私は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に

EDIT

This議論は、boost::filesystemの最小ヘッダのみのバージョンに関して。要約すると、これは存在しません。したがって、あなた自身の抽象ライブラリを構築し、クロスプラットフォームの機能を提供することになります。

Linuxでは、dirent.hがあり、これはPOSIX Cライブラリです。 Windowsの場合、Win32 APIを使用する必要があります。しかし、クロスプラットフォームと思われる、いわゆる "ディレクトリストリームライブラリ"もあります。here(ウェブサイトはドイツ語です)。

3

ブースト以外のソリューションには、システムに依存するコード(ブーストを使用する場合は がブーストに表示されません)が含まれます。そして、正確に と定義する必要があります:"./MyFile.xxx""MyFile.xxx" は同等ですか? "aaa/.../MyFile.xxx""MyFile.xxx"はどうですか?

私はこれを処理するような方法は、2つのデータメンバを持つクラスを定義することで、 std::string(常にUnixの内空 だろう)“接頭”と、パス のすべての要素を持つstd::vector<std::string>。このクラスには、必要な比較 関数が含まれており、システム依存コードを使用して コンストラクタを実装します。コンストラクタ自体は、ソースファイルであろう、と ソースファイルは、一般的に使用するディレクトリを指定するための手段-Iの 又は/Iによりヘッダを各変異体のための別のディレクトリを 使用、および選択することによって(マシン依存ヘッダを含むであろう)。ヘッダーに行くかもしれないものの一種 :Unix用

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() 超える反復、。 "."という要素がある場合は、".."のいずれかに対して、 を無視し、パスが空でない場合は、pop_back()を使用して、パスの先頭の 要素を削除します。その後、それはstd::stringため コンパレータで だけcharためcharComparecharMatchを使用するコンパレータを定義の問題、およびstd::lexicographical_compareまたは std::equal(サイズが同じであることを確認した後)だ(そしておそらく、さらに新しい クラス用) 。次のようなもの:

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とのソリューションは私にとっては問題ではない"と言っています。代替案を探しています。 –

関連する問題