我正在寻找一种方法来检查2个字符串在文件系统路径(目录)方面是否相同。例如,来自此集合的所有字符串在文件系统路径方面都是相同的:{/x
,\x
,//x
,/x/
},但这两个 - {{1} } /x
不是,即使/y
是/y
的符号链接。我要编写的程序应该像Linux一样工作,所以我正在寻找便携式解决方案。
修改
我只使用了只有头文件的boost库,所以使用/x
的解决方案对我来说并不合适。我知道windows API中有boost::filesystem
,有类似linux的东西吗?
答案 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()
删除顶部
路径的元素,如果路径不为空。之后,就是这样
只是定义比较器使用charCompare
和
charMatch
的{{1}}和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
。)
答案 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
,因为该文件夹实际上是相同的。