我如何“规范化"?使用 boost::filesystem 的路径名? [英] How do I "normalize" a pathname using boost::filesystem?

查看:34
本文介绍了我如何“规范化"?使用 boost::filesystem 的路径名?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们在应用程序中使用 boost::filesystem.我有一个完整"路径,它是通过将多个路径连接在一起而构建的:

We are using boost::filesystem in our application. I have a 'full' path that is constructed by concatenating several paths together:

#include <boost/filesystem/operations.hpp>
#include <iostream>
     
namespace bf = boost::filesystem;

int main()
{
    bf::path root("c:\some\deep\application\folder");
    bf::path subdir("..\configuration\instance");
    bf::path cfgfile("..\instance\myfile.cfg");

    bf::path final ( root / subdir / cfgfile);

    cout << final.file_string();
}

最终路径打印为:

c:somedeepapplicationfolder..configurationinstance..instancemyfile.cfg

这是一个有效的路径,但是当我向用户显示它时,我希望它被规范化.(注意:我什至不确定规范化"是否是正确的词为了这).像这样:

This is a valid path, but when I display it to the user I'd prefer it to be normalized. (Note: I'm not even sure if "normalized" is the correct word for this). Like this:

c:somedeepapplicationconfigurationinstancemyfile.cfg

早期版本的 Boost 有一个 normalize() 函数 - 但它似乎已被弃用和删除(没有任何解释).

Earlier versions of Boost had a normalize() function - but it seems to have been deprecated and removed (without any explanation).

我是否有理由不使用 BOOST_FILESYSTEM_NO_DEPRECATED 宏?有没有其他方法可以使用 Boost 文件系统库来做到这一点?还是应该写代码直接把路径作为字符串操作?

Is there a reason I should not use the BOOST_FILESYSTEM_NO_DEPRECATED macro? Is there an alternative way to do this with the Boost Filesystem library? Or should I write code to directly manipulating the path as a string?

推荐答案

Boost v1.48 及以上

你可以使用 boost::filesystem::canonical:

path canonical(const path& p, const path& base = current_path());
path canonical(const path& p, system::error_code& ec);
path canonical(const path& p, const path& base, system::error_code& ec);

http://www.boost.org/doc/libs/1_48_0/libs/filesystem/v3/doc/reference.html#canonical

v1.48 及以上版本还提供了用于解析符号链接的 boost::filesystem::read_symlink 函数.

v1.48 and above also provide the boost::filesystem::read_symlink function for resolving symbolic links.

正如其他答案中提到的,您无法标准化,因为 boost::filesystem 无法遵循符号链接.但是,您可以编写一个尽可能多地"规范化的函数(假设."和.."被正常处理),因为 boost 提供了确定文件是否为符号链接的能力.

As mentioned in other answers, you can't normalise because boost::filesystem can't follow symbolic links. However, you can write a function that normalises "as much as possible" (assuming "." and ".." are treated normally) because boost offers the ability to determine whether or not a file is a symbolic link.

也就是说,如果.."的父级是一个符号链接,那么你必须保留它,否则删除它可能是安全的,而删除."可能总是安全的.

That is to say, if the parent of the ".." is a symbolic link then you have to retain it, otherwise it is probably safe to drop it and it's probably always safe to remove ".".

它类似于操作实际的字符串,但稍微优雅一些​​.

It's similar to manipulating the actual string, but slightly more elegant.

boost::filesystem::path resolve(
    const boost::filesystem::path& p,
    const boost::filesystem::path& base = boost::filesystem::current_path())
{
    boost::filesystem::path abs_p = boost::filesystem::absolute(p,base);
    boost::filesystem::path result;
    for(boost::filesystem::path::iterator it=abs_p.begin();
        it!=abs_p.end();
        ++it)
    {
        if(*it == "..")
        {
            // /a/b/.. is not necessarily /a if b is a symbolic link
            if(boost::filesystem::is_symlink(result) )
                result /= *it;
            // /a/b/../.. is not /a/b/.. under most circumstances
            // We can end up with ..s in our result because of symbolic links
            else if(result.filename() == "..")
                result /= *it;
            // Otherwise it should be safe to resolve the parent
            else
                result = result.parent_path();
        }
        else if(*it == ".")
        {
            // Ignore
        }
        else
        {
            // Just cat other path entries
            result /= *it;
        }
    }
    return result;
}

这篇关于我如何“规范化"?使用 boost::filesystem 的路径名?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆