boost :: filesystem得到相对路径

itu*_*tun 27 c++ filesystems boost boost-filesystem

boost::filesystem库的哪些方法可以帮助我获得相对于另一条路径的路径?

我有一条路/home/user1/Downloads/Books和一条路/home/user1/.现在我想要一条路Downloads/Books.

mil*_*iez 32

在新版本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;
}
Run Code Online (Sandbox Code Playgroud)

  • 使用 boost::filesystem::relative 的一个缺点是它会尝试访问本地文件系统上提供的路径。因此,如果您只想使用与本地文件(例如 URL)无关的虚拟路径,那么 /sf/answers/2045508251/ 中的relativeTo 函数更有用。 (2认同)

Rob*_*oli 17

提供的答案中的代码在每一行都很长.假设你写了,namespace fs = boost::filesystem;那么这段代码可以让你大部分时间,并且看起来更容易给我看:

static fs::path relativeTo(fs::path from, 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.
   fs::path::const_iterator fromIter = from.begin();
   fs::path::const_iterator 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)
   fs::path finalPath;
   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;
}
Run Code Online (Sandbox Code Playgroud)

  • 这看起来比其他答案好得多. (2认同)
  • 该答案与内置“relative()”函数的新版本 Boost 的持续相关性在于,该版本不会规范化、解析符号链接,甚至不会检查路径是否存在。IOW,它可以在没有物理文件系统的情况下抽象地使用。 (2认同)

Mah*_*dsi 15

摘自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;
    }
Run Code Online (Sandbox Code Playgroud)

坚持在头文件中,它应该做你想要的.

示例电话:

boost::filesystem::path a("foo/bar"), b("foo/test/korv.txt");
std::cout << make_relative( a, b ).string() << std::endl;
Run Code Online (Sandbox Code Playgroud)


Nic*_*las 6

遗憾的是,Boost.Filesystem中不存在这样的功能.已被要求,但他们似乎并不关心.

你基本上必须手动完成.

Boost.Filesystem 1.60添加relative可用于处理此问题函数.