/x
,\x
,//x
,/x/
},但是这两个字符串 - /x
和/y
不同,即使/y
是/x
的符号链接。我要编写的程序应该适用于Linux和Windows,因此我正在寻找可移植的解决方案。
编辑:
我仅使用boost的头文件库,因此对于我来说,具有boost :: filesystem
的解决方案不可行。我知道Windows API中有UrlCompare
,那么Linux中是否有类似的东西呢?
/x
,\x
,//x
,/x/
},但是这两个字符串 - /x
和/y
不同,即使/y
是/x
的符号链接。我要编写的程序应该适用于Linux和Windows,因此我正在寻找可移植的解决方案。
编辑:
我仅使用boost的头文件库,因此对于我来说,具有boost :: filesystem
的解决方案不可行。我知道Windows API中有UrlCompare
,那么Linux中是否有类似的东西呢?
"./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()
删除路径的顶部元素,前提是路径不为空。之后,只需要定义比较器以使用charCompare
和charMatch
进行char
比较,并使用std::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
必须在源文件中;您不能将它们内联到标头中,因为标头不包括定义 charCompare
和 charMatch
的系统相关标头。)
std::string path1 = "c:\\folder\\";
std::string path2 = "c:\\folder\\folder\\..\\";
boost::filesystem::equivalent(boost::filesystem::path(path1), boost::filesystem::path(path2)
这段代码返回 true
,因为文件夹实际上是相同的。
std::filesystem::canonical
可能会有所帮助: https://dev59.com/1loU5IYBdhLWcg3w7aCP#56674900 - MasterHD