如何在c ++中比较(目录)路径?

时间:2011-12-14 12:35:10

标签: c++ path comparison cross-platform

我正在寻找一种方法来检查2个字符串在文件系统路径(目录)方面是否相同。例如,来自此集合的所有字符串在文件系统路径方面都是相同的:{/x\x//x/x/},但这两个 - {{1} } /x不是,即使/y/y的符号链接。我要编写的程序应该像Linux一样工作,所以我正在寻找便携式解决方案。

修改

我只使用了只有头文件的boost库,所以使用/x的解决方案对我来说并不合适。我知道windows API中有boost::filesystem,有类似linux的东西吗?

4 个答案:

答案 0 :(得分:3)

任何非Boost解决方案都将涉及系统相关代码(即 如果你使用Boost隐藏在Boost中)。你必须准确定义 “匹配”的含义:"./MyFile.xxx""MyFile.xxx" 比较平等?那么"aaa/.../MyFile.xxx""MyFile.xxx"呢?

我要处理的方法是定义一个包含两个数据成员的类, 带有“前缀”的std::string(总是如此 在Unix中为空),以及包含所有路径的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;
}

for Unix,with:

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 );
}

for Windows。

然后,构造函数将使用getHeader初始化标头,并且 迭代input.begin() + header.size()input.end(),打破 字符串到元素。如果遇到"."的元素, 忽略它,对于".."之一,请使用pop_back()删除顶部 路径的元素,如果路径不为空。之后,就是这样 只是定义比较器使用charComparecharMatch的{​​{1}}和charstd::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。)

答案 1 :(得分:2)

使用boost::filesystem库 - 这具有路径比较功能。

编辑:您可以尝试apr - 是的,它不是C ++,但它可以移植。

答案 2 :(得分:1)

就可移植性而言,Boost文件系统库可能很有用(documentation link)。更具体地说:path.hpp最有用,您可以使用路径比较。

修改

This关于gmane.org的讨论涉及boost::filesystem的最小标题版本。总结:这不存在。因此,您最终将构建自己的抽象库并为其提供跨平台功能。

在Linux下有dirent.h这是一个POSIX C库。对于Windows,您必须使用Win32 API。然而,还有一个所谓的“目录流库”,它似乎是跨平台的,可用here(网站是德语)。

答案 3 :(得分:1)

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

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

代码返回true,因为该文件夹实际上是相同的。