boost::filesystem
库中哪些方法可以帮助我获取相对于另一个路径的路径?
我有两个路径:/home/user1/Downloads/Books
和/home/user1/
。现在我想获取Downloads/Books
路径。
boost::filesystem
库中哪些方法可以帮助我获取相对于另一个路径的路径?
我有两个路径:/home/user1/Downloads/Books
和/home/user1/
。现在我想获取Downloads/Books
路径。
在新版本的 boost
(从1.60开始),您可以使用 boost::filesystem::relative
。 (此处查看文档。)
#include <boost/filesystem.hpp>
#include <iostream>
namespace fs = boost::filesystem;
int main()
{
fs::path parentPath("/home/user1/");
fs::path childPath("/home/user1/Downloads/Books");
fs::path relativePath = fs::relative(childPath, parentPath);
std::cout << relativePath << std::endl;
}
namespace fs = boost::filesystem;
那么这段代码将帮助你完成大部分工作,并且看起来更易于阅读: auto relativeTo( const fs::path& from, const fs::path& to )
{
// Start at the root path and while they are the same then do nothing then when they first
// diverge take the entire from path, swap it with '..' segments, and then append the remainder of the to path.
auto fromIter = from.begin();
auto toIter = to.begin();
// Loop through both while they are the same to find nearest common directory
while( fromIter != from.end() && toIter != to.end() && *toIter == *fromIter )
{
++toIter;
++fromIter;
}
// Replace from path segments with '..' (from => nearest common directory)
auto finalPath = fs::path{};
while( fromIter != from.end() )
{
finalPath /= "..";
++fromIter;
}
// Append the remainder of the to path (nearest common directory => to)
while( toIter != to.end() )
{
finalPath /= *toIter;
++toIter;
}
return finalPath;
}
relative
,它不会触及文件系统 - 请查看我的答案。 - PBS以下内容取自通过Nicol提供的链接:
template < >
path& path::append< typename path::iterator >( typename path::iterator begin, typename path::iterator end, const codecvt_type& cvt)
{
for( ; begin != end ; ++begin )
*this /= *begin;
return *this;
}
// Return path when appended to a_From will resolve to same as a_To
boost::filesystem::path make_relative( boost::filesystem::path a_From, boost::filesystem::path a_To )
{
a_From = boost::filesystem::absolute( a_From ); a_To = boost::filesystem::absolute( a_To );
boost::filesystem::path ret;
boost::filesystem::path::const_iterator itrFrom( a_From.begin() ), itrTo( a_To.begin() );
// Find common base
for( boost::filesystem::path::const_iterator toEnd( a_To.end() ), fromEnd( a_From.end() ) ; itrFrom != fromEnd && itrTo != toEnd && *itrFrom == *itrTo; ++itrFrom, ++itrTo );
// Navigate backwards in directory to reach previously found base
for( boost::filesystem::path::const_iterator fromEnd( a_From.end() ); itrFrom != fromEnd; ++itrFrom )
{
if( (*itrFrom) != "." )
ret /= "..";
}
// Now navigate down the directory branch
ret.append( itrTo, a_To.end() );
return ret;
}
把这段代码放进头文件里,它就会按照你的要求执行。
示例调用:
boost::filesystem::path a("foo/bar"), b("foo/test/korv.txt");
std::cout << make_relative( a, b ).string() << std::endl;
make_relative
。这可能是错误的(给定的代码似乎没有将make_relative
放在boost::filesystem
中),如果它是正确的,由于ADL,它是不必要的。 - MSaltersrelative
函数,该函数可用于处理这种情况。
#include <iostream>
#include <filesystem>
namespace fs = std::filesystem;
fs::path path("/home/user1/Downloads/Books");
fs::path base("/home/user1/");
std::cout << fs::relative(path, base) << '\n';
std::cout << path.lexically_relative(base) << '\n';
这将打印
"Downloads/Books"
"Downloads/Books"
namespace boost { namespace filesystem {
template <> path& path::append<path::iterator>(path::iterator begin, path::iterator end, const codecvt_type& cvt)
{
for( ; begin != end ; ++begin )
*this /= *begin;
return *this;
}
// Return path when appended to a_From will resolve to same as a_To
boost::filesystem::path make_relative( boost::filesystem::path a_From, boost::filesystem::path a_To )
{
a_From = boost::filesystem::absolute( a_From ); a_To = boost::filesystem::absolute( a_To );
boost::filesystem::path ret;
boost::filesystem::path::const_iterator itrFrom( a_From.begin() ), itrTo( a_To.begin() );
// Find common base
for( boost::filesystem::path::const_iterator toEnd( a_To.end() ), fromEnd( a_From.end() ) ; itrFrom != fromEnd && itrTo != toEnd && *itrFrom == *itrTo; ++itrFrom, ++itrTo );
// Navigate backwards in directory to reach previously found base
for( boost::filesystem::path::const_iterator fromEnd( a_From.end() ); itrFrom != fromEnd; ++itrFrom )
{
if( (*itrFrom) != "." )
ret /= "..";
}
// Now navigate down the directory branch
ret.append( itrTo, a_To.end() );
return ret;
}
} } // namespace boost::filesystem