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

标签 c++ path comparison cross-platform

我正在寻找一种方法来检查 2 个字符串在文件系统路径(目录)方面是否相同。例如,此集合中的所有字符串在文件系统路径方面都是相同的:{/x,\x,//x,/x/},但是这两个 - /x/y 不是,即使 /y 是符号链接(symbolic link)到 /x。我要编写的程序应该既适用于 Linux 也适用于 Windows,因此我正在寻找可移植的解决方案。

编辑:

我只使用 boost 的仅 header 库,所以 boost::filesystem 的解决方案对我来说不合适。我知道在 windows API 中有 UrlCompare,在 linux 中有类似的东西吗?

最佳答案

任何非 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;
}

对于 Unix,具有:

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

适用于 Windows。

然后构造函数将使用 getHeader初始化标题,和 遍历 input.begin() + header.size()input.end() , 打破 把字符串向上分解成元素。如果遇到"."的元素, 忽略它,对于 ".." 之一, 使用 pop_back()删除顶部 路径的元素,前提是路径不为空。之后,就是 只是定义要使用的比较器的问题 charComparecharMatch对于 char , 和 std::lexicographical_compare要么 std::equal (在验证大小相等之后)与 std::string 的比较器(可能还有你的新 类(class))。像这样的东西:

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 必须在源文件中;您不能将它们内联到标题中, 其中不包括定义的系统相关 header charComparecharMatch .)

关于c++ - 如何在 C++ 中比较(目录)路径?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8504571/

相关文章:

c++ - unique_ptr<T> 用于数组特化的 lambda 自定义删除器

windows - 递归路径

c++ - 操作 wchar 时遇到问题

jQuery DOM 元素创建与innerHTML

mysql - Mysql 查询中的奇怪行为

java - 快速数字比较的最佳原始类型?

c++ - 哪些 iomanip 操纵器是 'sticky' ?

c++ - Kurento:无法接收来自 GStreamer 元素的回调 "cutter"

c++ - inline 或 constexpr 函数的多个定义的含义

java - 为什么 servletContext.getRealPath 在 tomcat 8 上返回 null?